一、C++万能编译头文件

#include<bits/stdc++.h>

VS2017添加万能头文件

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std; int main(){
cout << "Hello world!" << endl;
return 0;
}

#include<bits/stdc++.h>
using namespace std; int main(){
cout << "Hello world!" << endl;
return 0;
}

注意:

1、目前POJ还不支持<bits/stdc++.h>(G++、C++都不支持)。HDU部分支持(G++支持,C++不支持)。

其他国外的oj,还有台湾的oj都支持,CF,Topcoder也都支持。

2、降低编译速度、造成CE。

主要用途:减少代码量

二、预编译

预处理宏

#define long long ll

条件编译

#define DEBUG
int main(){
#ifdef DEBUG
cout << "Hello world!" << endl;
#endif
return 0;
}

C++/C语言中条件编译相关的预编译指令,包括 #define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined。

#define 定义一个预处理宏

#undef 取消宏的定义

#if 编译预处理中的条件命令,相当于C语法中的if语句

#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句

#ifndef 与#ifdef相反,判断某个宏是否未被定义

#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if

#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else

#endif #if, #ifdef, #ifndef这些条件命令的结束标志.

defined  与#if, #elif配合使用,判断某个宏是否被定义

详情

主要用途:替换、选择性编译

三、文件输入/文件输出

#define DEBUG
int main(){
#ifdef DEBUG
freopen("input.in", "r", stdin);
//freopen("output.out", "w", stdout);
#endif
int n;
scanf("%d",&n);
//cout << "Hello world!" << endl;
return 0; }

而我常用的是

freopen("input.in", "r", stdin);
//直接使用,提交的时候注释即可

详情

主要用途:减少DEBUG中繁琐的复制/粘贴/输入操作

四、程序运行时间

#include<iostream>
#include<ctime>
using namespace std;
#define DEBUG
int main(){
int n;
scanf("%d",&n);
//cout << "Hello world!" << endl;
#ifdef DEBUG
printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
return 0;
}

详情

注意:此代码记录输入时间,故应该配合文件输入/文件输出代码

主要用途:与文件输入/文件输出同时使用,初步计算程序运行时间

五、寄存器变量

register

常见宏编译

#define RI register int

对于一些频繁使用的变量,可以声明时加上该关键字,运行时可能会把该变量放到CPU寄存器中,只是可能,因为寄存器的空间是有限的,不保证有效。特别是你变量多的时候,一般还是丢到内存里面的。

比较下面两段程序:

register int a=0;
for(register int i=1;i<=999999999;i++)a++;
int a=0;
for(int i=1;i<=999999999;i++)a++;

优化:0.2826 second

不优化:1.944 second

详情

主要用途:减少程序运行时间

六、typedef

typedef long long ll;
//typedef __int128 lll;

类似于宏编译#define

#define long long ll;
#define __int128 lll;

详情

主要用途:减少代码量

七、cin和cout取消同步

ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

详情

主要用途:减少输入输出的时间

八、快速输入输出函数

template <class T>
inline void scan_d(T &ret)
{
char c;
ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0'), c = getchar();
}
}

详情

主要用途:减少输入输出的时间

九、endl、"\n"和'\n'

"\n"

"\n"表示搜索一个字符串,只有一个数据是回车符

'\n'

'\n' 表示一个字符,两者在输出上是一样的!

endl

  1. 在c++中,终端输出换行时,用cout<<......<<endl 与 “\n”都可以,这是初级的认识。但二者有小小的区别,用endl时会刷新缓冲区,使得栈中的东西刷新一次,但用“\n”不会刷新,它只会换行,盏内数据没有变化。但一般情况,二者的这点区别是很小的,在大的程序中可能会用到。建议用endl来换行.
  2. endl除了写’\n’进外,还调用flush函数,刷新缓冲区,把缓冲区里的数据写入文件或屏幕.考虑效率就用’\n’.
  3. cout << endl;除了往输出流中插入一个’\n’还有刷新输出流的作用.
  4. cout << endl; 等价于: cout << ‘\n’ << flush;
  5. 在没有必要刷新输出流的时候应尽量使用cout << ‘\n’, 过多的endl是影响程序执行效率低下的因素之一.

详情

主要用途:提高程序运行效率

十、常量

const int N=1000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;

主要用途:提高代码复用性

十一、内联函数

inline int max(int a,int b){
return a > b ? a:b;
}

由编译器在编译时会在主程序中把函数的内容直接展开替换,减少了内存访问,但是这并不是适用于各种复杂以及递归式的函数,复杂函数编译器会自动忽略inline

详情

主要用途:提高程序运行效率

十二、默认参数

可用于逆元的取模快速幂函数

int PowerMod(int a, int b=MOD-2, int c=MOD){
int ans = 1;
a = a % c;
while(b>0){
if(b % 2 == 1)
ans = (ans * a) % c;
b >>= 1;
a = (a * a) % c;
}
return ans;
}

详情

主要用途:提高函数复用性,减少代码量

十三、奇偶判断

n%2
n&1

其中&1的效率高于%2

详情

%2的汇编代码为

movl    _x, %eax
movl $LC0, (%esp)
movl %eax, %edx //(del)
shrl $31, %edx //(del)
addl %edx, %eax //(del)
andl $1, %eax
subl %edx, %eax //(del)
movl %eax, 4(%esp)
movl %eax, _x

&1的汇编代码为

movl    _x, %eax
movl $LC0, (%esp)
andl $1, %eax
movl %eax, 4(%esp)
movl %eax, _x

主要用途:提高程序运行效率

十四、乘和除的位运算

x <<= 1;
x *= 2;

例如上面这两句,都是把x乘2,但真的用位运算会快么,其实他们理论上是一样的,在被g++翻译成汇编后,两者的语句都是

addl    %eax, %eax1

它等价于 x = x + x。所以在这里位运算并没有任何优化。那么把乘数扩大呢,比如乘10,x *= 10的汇编语言为

leal    (%eax,%eax,4), %eax
addl %eax, %eax

翻译过来就是

x = x + x*4;
x = x + x;

而那些喜欢用(x << 3 + x << 1)的人自己斟酌!

但是位运算在某些地方是非常有用的,比如除法,右移的汇编代码为

movl    _x, %eax
sarl %eax
movl %eax, _x
movl _x, %eax

而除二的汇编代码为

movl    _x, %eax
movl %eax, %edx //(del)
shrl $31, %edx //(del)
addl %edx, %eax //(del)
sarl %eax
movl %eax, _x
movl _x, %eax

可以看到,右移会比除快很多。

详情

主要用途:提高程序运行效率

十五、变量交换

swap函数效率高于a ^= b ^= a ^= b

详情

(a ^= b ^= a ^= b)的汇编代码

movl    _b, %edx
movl _a, %eax
xorl %edx, %eax
xorl %eax, %edx
xorl %edx, %eax
movl %eax, _a
xorl %eax, %eax
movl %edx, _b

(int t = a;a = b,b = t;)的汇编代码

movl    _a, %eax
movl _b, %edx
movl %eax, _b
xorl %eax, %eax
movl %edx, _a

主要用途:提高程序运行效率

十六、lowbit函数

x & (-x)
int lowbit(int x){
return x&(-x);
}

详情

主要用途:提高程序运行效率

十七、2的幂判断

x > 0 ? ( x & (x - 1)) == 0 : false

详情

主要用途:提高程序运行效率

十八、短路运算符

短路运算符:一旦可以确定了表达式的真假值时,直接返回真假值

详情

主要用途:提高程序运行效率

十九、非零即真

if(x)

详情

主要用途:提高程序运行效率

二十、 取模优化

//设模数为 mod
inline int inc(int x,int v,int mod){x+=v;return x>=mod?x-mod:x;}//代替取模+
inline int dec(int x,int v,int mod){x-=v;return x<0?x+mod:x;}//代替取模-

详情

主要用途:提高程序运行效率

二十一、加法优化

用++i代替i++,后置++需要保存临时变量以返回之前的值,在 STL 中非常慢。

详情

主要用途:提高程序运行效率

二十二、结构优化

如果要经常调用a[x],b[x],c[x]这样的数组,把它们写在同一个结构体里面会变快一些,比如f[x].a, f[x].b, f[x].c

指针比下标快,数组在用方括号时做了一次加法才能取地址!所以在那些计算量超大的数据结构中,你每次都多做了一次加法!!!在 64 位系统下是 long long 相加,效率可想而知。

详情

主要用途:提高程序运行效率

二十三、对拍程序

虽然肉眼debug的能力也很重要,但有的时候一直手打数据测试两三天也没有必要。

详情

主要用途:提高DEBUG效率,寻找问题数据

二十四、O1,O2,O3编译优化

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")

详情

主要用途:提高程序运行效率

二十五、扩栈

C++版本一

写在main的开始

int size = 256 << 20; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp\n" :: "r"(p));

C++版本二

#pragma comment(linker, "/STACK:102400000,102400000")

C++版本三

64位版本

extern int main2(void) __asm__ ("main2");
int main2(){ exit(0); }//在这里写main函数
int main(){
int size=64<<20; char *p=(char*)malloc(size)+size;
__asm__ __volatile__("movq %0, %%rsp\n" "pushq $exit\n" "jmp main2\n" :: "r"(p));
}

详情

主要用途:提高系统栈的存储空间

二十六、memset和memcpy以及memmove

函数效率都非常高,比循环的速度快很多

若原code:

for(int i=l;i<=r;++i) a[i]=0;
for(int i=l;i<=r;++i) a[i]=b[i];
for(int i=l;l<=r;++i) a[i]=b[i],b[i]=0;

memset(a+l,0,r-l+1<<2);
memcpy(a+l,b+l,r-l+1<<2);
memmove(a+l,b+l,r-l+1<<2);
/* ------- */
memset(a+l,0,(r-l+1)*sizeof(a[0]));
memcpy(a+l,b+l,(r-l+1)*sizeof(a[0]));
memmove(a+l,b+l,(r-l+1)*sizeof(a[0]));

详情

主要用途:提高程序运行效率

二十七、YES/NO输出(三元运算符)

cout<<(ans?"YES":"NO")<<endl;

详情

主要用途:提高程序可读性

二十八、输出空格分隔、末尾无空格的数组

for(int i=1;i<=n;i++){
printf("%d%c",a[i]," \n"[i==n]);
}

详情

主要用途:减少代码量

二十九、构造函数

struct node{
int u,v,w;
node(){};
node(int u,int v,int w):u(u),v(v),w(w){}
};

详情

主要用途:减少代码量

三十、常用C++库函数 (STL)

函数 作用
sort 排序
memset 赋值
next_permutation 全排列
max 最大值
min 最小值
swap 交换
exit 退出程序
__builtin_popcount 一个数的二进制表示中有多少位是1
strlen 字符数组长度

主要用途:减少代码量

ACM/OI中C++常用优化(实用/调试/技巧)代码(语法)的更多相关文章

  1. Chrome 实用调试技巧

    Chrome 实用调试技巧 2016-07-23 如今Chrome浏览器无疑是最受前端青睐的工具,原因除了界面简洁.大量的应用插件,良好的代码规范支持.强大的V8解释器之外,还因为Chrome开发者工 ...

  2. Java常用的输出调试技巧

    --------siwuxie095                 Eclipse 开发中常用的输出调试技巧:     先在左侧的 Package Explorer,右键->New->J ...

  3. 【前端】javascript中10常用的个小技巧总结

    javascript中10常用的个小技巧总结 本文转自:http://www.cnblogs.com/libin-1/p/6756393.html 1. new Set() 可能有人知道ES6中提供了 ...

  4. 浅谈OI中的底层优化!

    众所周知,OI中其实就是算法竞赛,所以时间复杂度非常重要,一个是否优秀的算法或许就决定了人生,而在大多数情况下,我们想出的算法或许并不那么尽如人意,所以这时候就需要一中神奇的的东西,就是底层优化: 其 ...

  5. CSS2.0中最常用的18条技巧

    一.使用css缩写 使用缩写可以帮助减少你CSS文件的大小,更加容易阅读.  具体内容请浏览:CSS常用缩写语法 二.明确定义单位,除非值为0. 忘记定义尺寸的单位是CSS新手普遍的错误.在HTML中 ...

  6. 你应该知道的CSS2.0中最常用的18条技巧

    一.使用css缩写 使用缩写可以帮助减少你CSS文件的大小,更加容易阅读.  具体内容请浏览:CSS常用缩写语法 二.明确定义单位,除非值为0. 忘记定义尺寸的单位是CSS新手普遍的错误.在HTML中 ...

  7. Chrome实用调试技巧

    如今Chrome浏览器无疑是最受前端青睐的工具,原因除了界面简洁.大量的应用插件,良好的代码规范支持.强大的V8解释器之外,还因为Chrome开发者工具提供了大量的便捷功能,方便我们前端调试代码,我们 ...

  8. Android Studio 实用调试技巧

    Android Studio 是个发工具,其自身带调式环境是很强大的,我们要摆脱只会使用Log打印日志的低效的方法,掌握高级调试技巧对每个Android开发者都是很必要的,废话少说,直入正题 调试方式 ...

  9. [No0000194]聊聊 Chrome DevTools 中你可能不知道的调试技巧

    对于前端开发者来说,ChromeDevTools 绝对是不可或缺的调试工具,我们常用的调试方法包含一些console等,而ChromeDevTools 其实很强大,下面来聊聊一些你可能不知道的debu ...

  10. Mac OS X 中一些常用的命令行技巧

    一.网络设置相关 1.网卡的物理地址的动态重置 出于某些需求,例如网络中的 IP 地址或网络帐号与网卡物理地址绑定,使得多个设备无法切换上网,可尝试临时更改物理地址.不过,系统偏好设置是不能修改网卡物 ...

随机推荐

  1. Vue01-简介与入门

    Vue 01. 简介 1.1 前端三大框架 目前前端最流行的三大框架: Vue React angular 1.2 Vue简介 Vue (读音 /vjuː/,类似于 view) ,也可以写成Vue.j ...

  2. 常用【描述性统计指标】含义(by python)

    统计学有时候会被误解,好像必须有大量的样本数据,才能使统计结果有意义.这会让我们觉得统计学离我们的日常生活很遥远. 其实,如果数据的准确度高的话,少量的样本数据同样能反映出真实的情况.比如,很多国家选 ...

  3. 不要用第三方日志包了Microsoft.Extensions.Logging功能就很强大

    在.NET中,Microsoft.Extensions.Logging是一个广泛使用的日志库,用于记录应用程序的日志信息.它提供了丰富的功能和灵活性,使开发人员能够轻松地记录各种类型的日志,并将其输出 ...

  4. 数字孪生和GIS结合能为智慧社区带来怎样的改变?

    数字孪生和地理信息系统(GIS)是当今智慧社区发展中的两个重要技术,它们的结合将为智慧社区带来根本性的改变和巨大的发展机遇.这种结合将深刻影响社区的规划.建设.运营和管理,为居民创造更智能.便利.宜居 ...

  5. Windows Server 2016配置NTP客户端

    前提:开通Windows Time 服务 输入services.msc进入服务管理界面,找到Windows Time 开启服务. 情况1:可以直接设置NTP时钟 控制面板--时钟和区域--设置时间和日 ...

  6. 这一次,弄明白JS中的文件相关(一):概念篇

    概念是学习的基础.在学习JS中的文件操作之前,先把文件相关的各种概念搞清楚,很有好处. 1. 二进制: 计算机硬件仅能处理和存储二进制数据,所以不管是你正在写的代码,还是你硬盘里的小姐姐,都是以二进制 ...

  7. Langchain-Chatchat项目:3-Langchain计算器工具Agent思路和实现

      本文主要讨论Langchain-Chatchat项目中自定义Agent问答的思路和实现.以"计算器工具"为例,简单理解就是通过LLM识别应该使用的工具类型,然后交给相应的工具( ...

  8. xpath语法与lxml库详解

    xpath语法与lxml库 摘要:本文详细介绍了xpath语法,lxml库的使用以及两者的结合使用 注:平常爬虫运用的Xpath不是来自element中通过Chrome插件XPath Helper写出 ...

  9. 拥抱Serverless释放生产力,探索华为云Serverless车联网最佳实践

    华为云Serverless车联网场景解决方案,以FunctionGraph为核心的Serverless化组合方案,使用FunctionGraph.OBS.DIS等技术,可以实现架构的灵活扩展,在出行高 ...

  10. iOS代码安全加固利器:深入探讨字符串和代码混淆器的作用

    ​ 在网上搜"代码混淆"关键词,可以看到n多教程.包括本篇博客,大部分重要内容也是从网上各位大神的博客里面看到然后摘取和总结出来的.虽然网上都有,但是对于我个人来说,很难找到一篇博 ...