ACM/OI中C++常用优化(实用/调试/技巧)代码(语法)
一、C++万能编译头文件
#include<bits/stdc++.h>
从
#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 DEBUGcout << "Hello world!" << endl;#endifreturn 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 DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout);#endifint n;scanf("%d",&n);//cout << "Hello world!" << endl;return 0;}
详情
主要用途:减少DEBUG中繁琐的复制/粘贴/输入操作
四、程序运行时间
#include<iostream>
#include<ctime>
using namespace std;
#define DEBUG
int main(){int n;scanf("%d",&n);//cout << "Hello world!" << endl;#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);#endifreturn 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
- 在c++中,终端输出换行时,用cout<<......<<endl 与 “\n”都可以,这是初级的认识。但二者有小小的区别,用endl时会刷新缓冲区,使得栈中的东西刷新一次,但用“\n”不会刷新,它只会换行,盏内数据没有变化。但一般情况,二者的这点区别是很小的,在大的程序中可能会用到。建议用endl来换行.
- endl除了写’\n’进外,还调用flush函数,刷新缓冲区,把缓冲区里的数据写入文件或屏幕.考虑效率就用’\n’.
- cout << endl;除了往输出流中插入一个’\n’还有刷新输出流的作用.
- cout << endl; 等价于: cout << ‘\n’ << flush;
- 在没有必要刷新输出流的时候应尽量使用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
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 |
字符数组长度 |
详情
主要用途:减少代码量
参考文章:
https://www.cnblogs.com/xenny/p/9410888.html
https://blog.csdn.net/JacaJava/article/details/78336840
https://blog.csdn.net/chencsmat/article/details/47778757
ACM/OI中C++常用优化(实用/调试/技巧)代码(语法)相关推荐
- C语言:实用调试技巧
目录 C语言:实用调试技巧 1.什么是bug? 2.调试是什么?有多重要? 3.debug和release的介绍 4.Windows环境调试介绍 5.一些调试的实例 6.如何写出好(易于调试)的代码 ...
- 前端:CSS/15/全局CSS设置,常用的兼容性调试技巧,CSSHACK
全局CSS设置 1,清除所有的标记的内外边距 body,ul,li,a,img,p,input{margin:0;padding:0;} 2,去除项目符号或编号前面的符号 ul,ol,li{list- ...
- LaTeX中一些常用符号及编写技巧
博客中阅读效果更佳哦:LaTeX中一些常用符号及编写技巧 希腊字母 小写形式 代码 大写形式 代码 α \alpha A \Alpha β \beta B \Beta δ \delta Δ \Delt ...
- rust原地复活_rust腐蚀游戏新手入门必知小技巧 Rust腐蚀游戏中的12个实用小技巧...
rust腐蚀游戏新手入门必知小技巧,想必还有很多小伙伴还不太了解,下面小编给大家带来了Rust腐蚀游戏中的12个实用小技巧,一起来看看吧. rust腐蚀游戏新手入门必知小技巧 Rust腐蚀游戏中的12 ...
- rust腐蚀网页游戏_Rust腐蚀游戏中的12个实用小技巧
Rust腐蚀游戏中的12个实用小技巧 2020-08-05作者:网络来源:网络 Rust是一款第一人称生存网络游戏,有点像野外求生,但这款游戏内容则更加丰富.刺激.血腥. 在这款游戏中玩家的第一任务就 ...
- C语言第二十课:实用调试技巧
目录 前言: 一.Bug: 二.调试: 1.调试是什么: 2.调试的基本步骤: 3. Debug 与 Release : 三.在Windows环境下进行调试: 1.调试环境的准备: 2.调试的快捷键: ...
- 实用调试技巧 Debug Release F10 F11 初始化 越界访问 堆栈 模拟实现库函数
目录 一.什么是bug 二.调试是什么?有多重要? 1.调试 2.调试的基本步骤 三.Debug和Release 四.windows环境调试介绍 1.调试环境的准备 2.学会快捷键 Ctrl+U 改大 ...
- C语言之实用调试技巧
什么是bug? 调试是什么?有多重要? debug和release的介绍. windows环境调试介绍. 一些调试的实例. 如何写出好(易于调试)的代码. 编程常见的错误. 一. 什么是bug? 第一 ...
- Visual Studio中11个强大的调试技巧和方法
调试是软件开发周期中很重要的一部分.它具有挑战性,同时也很让人疑惑和烦恼.总的来说,对于稍大一点的程序,调试是不可避免的.最近几年,调试工具的发展让很多调试任务变的越来越简单和省时. 这篇文章总结了可 ...
最新文章
- linux用户态驱动--VIFIO、IOMMU、UIO(二)
- WPF 第一个创建的窗体会作为Application.Current.MainWindow
- elk 搜索 语法_ELK从入门到还未精通(二)——ElasticSearch上篇
- 外贸想做好开发客户和地推?就一定要用这个软件!
- graphpad细胞增殖曲线_肿瘤干细胞?居然被这两个新加坡人轻松干掉了?
- PRML-系列一之1.2.5~1.2.6
- [docker][win10]安装的坑
- layui 树状图默认全部展开_SolidWorks 钣金展开基础设定
- ftp 服务器的主动模式和被动模式
- 【TWVRP】基于matlab改进的遗传算法求解带时间窗约束多卫星任务规划问题【含Matlab源码 1774期】
- 微信点餐系统技术总结
- 利用python实现压韵(双压版)
- 硬盘安装linux镜像文件iso安装,通过ISO文件硬盘安装Ubuntu系统
- (转)使用jsonp帮助你知道关注的他或她QQ音乐中搜藏了什么歌曲
- C++ getline()函数的用法
- 外观模式 ------模拟电脑主机调用其他硬件和软件
- jQuery 实现带下拉提示且自动填充的邮箱
- 极光笔记 | 用 WhatsApp 进行海外用户运营的 N 个理由
- 天天生鲜项目从0开始
- 全世界最酷的软件!谷歌地球重磅更新
热门文章
- controller需要捕获异常吗_Spring之Controller异常处理
- c语言如果读不到数据就跳过,4,VS常见问题解决(一闪而过、等问题)不断更新...
- mysql 取一行_MySql – 如何获取上一行中的值和下一行中的值?
- python怎么调出某年某月日历_Python 写的计算指定年指定月日历的脚本
- 手机进不了recovery模式了 怎么办
- matlab保存变量的值,怎么不能保存之前的变量值?求解
- mysql实现日志系统_基于Hadoop/CloudBase/MySQL的日志分析系统的设计与实现
- dev chartcontrol获取x y轴的值_终于,奔驰强势接手了腾势X
- mysql redis qps_Redis QPS测试
- 七十七、React中的propTypes,defaultProps和生命周期函数