在写代码的时候,我们常常会用一些小技巧,下面做简单介绍

一、o1+o2+o3(常数优化)

如题,开优化开关。

有的OJ上有O2优化选项,当然,你也可以这样:在代码开头这样加一句:

#pragma GCC optimize("O1")
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")

o1+o2+o3

(逃~

Tips:此方法对STL非常有效!(NOIP赛场上我不知道能不能用,建议不要用)

二、 inline 关键字(常数优化)

可以在一个函数的最开始加上inline,如:

inline int max(int a, int b)
{
if (a < b)
return b;
return a;
}

inline example

意义:在编译时,把这个函数放到使用它的地方,如:

inline int max(int a, int b)  _
{ \
if (a < b) |
return b; }----------.
return a; | |
} _/ |
|
int main() | 编译时
{ | 直接包
int a, b, c; | 含进去,
cin >> a >> b >> c; | 加快程
cout << max(a, b) << endl; <----------| 序运行
| 速度。
cout << max(a, c) << endl; <----------|
|
cout << max(b, c) << endl; <----------/
return ;
}

inline example

使用贴士:

  1. 不要试图给递归函数加inline,这样可能会更慢!
  2. 不要试图给调用多次且代码量很大(即较复杂) 的非递归函数加inline, 这样并不会优化!
  3. 本方法应该给调用多次或复杂度较低的函数使用(如:min, max, fast_IO相关函数)。

三、register 关键字(常数优化)

可以在一个变量声明的类型前面加上这个关键字。例:

// example #1:
register int a;
// example #2:
register long long b[];
// example #3:
struct node1 {
int rank;
int num;
};
register node1 c;
// example #4:
register struct node2 {
int a, b;
int c;
} d;

register example

原理:我们运行的程序会放在内存里,所以访问速度还是较慢,所以我们可以将常用的变量放在离CPU更近的寄存器里(即register)。

使用小贴士:

  1. register的变量只能在函数里声明!!!(这也很好理解)
  2. 如上面 example #4,register可以写在struct开头。
  3. 因为寄存器空间有限,所以请只给反复使用的变量加register。(e.g.循环变量i, j, k

四、template + typename模板

可以给一个函数声明成template + typename的形式。如:

// example:
template <typename _Tp>
_Tp max(_Tp a, _Tp b)
{
if (a > b)
return a;
return b;
}
// use:
int x, y;
cin >> x >> y;
cout << max(x, y) << endl;
cout << max<int>(x, y) << endl; //这两行等价

template+typename example

可以看到,声明这种函数的方法是在开头加上

template <typename type1, typename type2, ...> // 类型个数任意 

注意:若一个typename(即类型)不是该函数的一个输入参数,则需用<...>的形式告诉函数这个typename的类型!

五、fread大招

先给代码嘤嘤嘤

char BufferRead[ << ];
int rLen = , rPos = ;
inline int Getchar(){
if (rPos == rLen) rPos = , rLen = fread(BufferRead, , << , stdin);
if (rPos == rLen) return EOF;
return BufferRead[rPos++];
}

fread版Getchar

说明:

  1. fread比getchar快,所以用fread优化程度更高
  2. 若本地运行且不加freopen,那么会出错(无休止的读入)!(因为fread会读满1 << 15个字节,而从文件读入时会读到文件结束符从而停止读入,不会出问题)
  3. 不知道fread可以通过这篇文章简要了解一下

六、快读整数(fast_IO #1

代码还是很简单的,如下:

template <typename _TpInt>
inline _TpInt read()
{
register int flag = ;
register char c = Getchar();
while ((c > '' || c < '') && c != '-')
c = Getchar();
if (c == '-') flag = -, c = Getchar();
register _TpInt init = (c & );
while ((c = Getchar()) <= '' && c >= '')
init = (init << ) + (init << ) + (c & );
return init * flag;
}

fast_IO #1

几点说明:

  1. 此方法的原理是:十进制,一位一位读入
  2. flag 是负数标记
  3. (c & 15)'0'ASCII码是48,(c & 15)此处等于(c % 16),所以本句(c & 15)的意义是c-'0'
  4. (init << 3) + (init << 1) = (init * 8) + (init * 2) = (init * 10)
  5. typename:可以读不同的类型

Tips:'&''<<'是位运算,关于位运算,可以上百度查资料

应用例子:

int a;
long long b;
short c;
a = read<int>();
b = read<long long>();
c = read<short>();

fast_IO #1 example

七、快读实数(fast_IO #2

仿照整数快读,写出实数快读:

template <typename _TpRealnumber>
inline double readr()
{
register int flag = ;
register char c = Getchar();
while ((c > '' || c < '') && c != '-')
c = Getchar();
if (c == '-') flag = -, c = Getchar();
register _TpRealnumber init = (c & );
while ((c = Getchar()) <= '' && c >= '')
init = init * + (c & );
if (c != '.') return init * flag;
register _TpRealnumber l = 0.1;
while ((c = Getchar()) <= '' && c >= '')
init = init + (c & ) * l, l *= 0.1;
return init * flag;
}

fast_IO #2

没什么好说明的。

应用例子:

float d;
double e;
d = readr<float>();
e = readr<double>();

fast_IO #2 example

八、快写整数(fast_IO #3

使用递归执行。

template <typename _TpInt>
inline void write(_TpInt x)
{
if (x < ) {
putchar('-');
write<_TpInt>(~x + );
}
else {
if (x > ) write<_TpInt>(x / );
putchar(x % + '');
}
}

fast_IO #3

 

说明:

  1. (~x+1) = -x,此处是为了unsigned型整数而写此句
  2. 若去掉 if (x > 9),则会死循环
  3. 本函数不可用于输出某种有符号类型的最小数!会无限输出负号!!!e.g.
    • write<int>(-2147483648);
    • write<short>(-65536);
    • etc...

应用例子:

write<int>();
printf("\n");
write<short>(-);
printf("\n");
write<int>(-);
printf("\n");
long long n = ;
write<long long>(n);
printf("\n");

fast_IO #3 example

尾声:给个模板吧

 // luogu-judger-enable-o2
/*
Problem: C++ 代码模板
Author: 航空信奥
Date: 2018/08/02
*/
#pragma GCC optimize("O1")
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <set>
#define lowbit(a) ((a) & (~a + 1)) // define 快
using namespace std;
namespace AuthorName { // 防重名
inline char Getchar();
template <typename _TpInt> inline _TpInt read();
template <typename _TpRealnumber> inline double readr();
template <typename _TpInt> inline void write(_TpInt x);
template <typename _TpSwap> inline void swap(_TpSwap &x, _TpSwap &y); int main()
{
// here : DO SOMETHING
return ;
} char BufferRead[ << ];
int rLen = , rPos = ;
inline char Getchar()
{
if (rPos == rLen) rPos = , rLen = fread(BufferRead, , << , stdin);
if (rPos == rLen) return EOF;
return BufferRead[rPos++];
} template <typename _TpInt>
inline _TpInt read()
{
register int flag = ;
register char c = Getchar();
while ((c > '' || c < '') && c != '-')
c = Getchar();
if (c == '-') flag = -, c = Getchar();
register _TpInt init = (c & );
while ((c = Getchar()) <= '' && c >= '')
init = (init << ) + (init << ) + (c & );
return init * flag;
} template <typename _TpRealnumber>
inline double readr()
{
register int flag = ;
register char c = Getchar();
while ((c > '' || c < '') && c != '-')
c = Getchar();
if (c == '-') flag = -, c = Getchar();
register _TpRealnumber init = (c & );
while ((c = Getchar()) <= '' && c >= '')
init = init * + (c & );
if (c != '.') return init * flag;
register _TpRealnumber l = 0.1;
while ((c = Getchar()) <= '' && c >= '')
init = init + (c & ) * l, l *= 0.1;
return init * flag;
} template <typename _TpInt>
inline void write(_TpInt x)
{
if (x < ) {
putchar('-');
write<_TpInt>(~x + );
}
else {
if (x > ) write<_TpInt>(x / );
putchar(x % + '');
}
} template <typename _TpSwap>
inline void swap(_TpSwap &x, _TpSwap &y)
{
_TpSwap t = x;
x = y;
y = t;
}
} int main()
{
AuthorName::main();
return ;
}

C++ 代码小技巧(一)的更多相关文章

  1. 一些代码小技巧&经典代码

    请说明逻辑与(&&)在下边表达式中起到的重要作用 count != 0 && sum/count 答:该表达式使用逻辑与(&&)来确保 sum/coun ...

  2. C# 代码小技巧

    一 .自动属性. 1.vs下输入prop,Tab键就出现了.   2.有了自动属性,我们不用再额外为一个类的每个公共属性定义一个私有字段(实际上没多大用处的字段), 但是通过反射还是可以看到对应的私有 ...

  3. 小技巧找出一个php的cron脚本出问题的代码行

    这个小技巧虽然很小,但是很有用. 我写了一个cron脚本,但是隔一天发现,这个昨天的cron脚本还一直在跑着,没有停下来,一定是里面有个程序堵住了. 但是如果我重新跑又需要很多时间.这个怎么办? 现在 ...

  4. Android课程---Android Studio使用小技巧:提取方法代码片段

    这篇文章主要介绍了Android Studio使用小技巧:提取方法代码片段,本文分享了一个快速复制粘贴方法代码片段的小技巧,并用GIF图演示,需要的朋友可以参考下 今天来给大家介绍一个非常有用的Stu ...

  5. Android Studio使用小技巧:提取方法代码片段

    http://www.jb51.net/article/65510.htm 今天来给大家介绍一个非常有用的Studio Tips,有些时候我们在一个方法内部写了过多的代码,然后想要把一些代码提取出来再 ...

  6. Postman使用小技巧 - 用Postman生成Request代码

    Postman这款工具可以让你很方便的测试你的Web API,那如果你实在是没办法用Postman,必须手写代码,又或者你有别的需求是Postman没法实现的,你必须写一个特殊的script或App来 ...

  7. 代码对齐 分类: C#小技巧 2014-04-17 14:45 166人阅读 评论(0) 收藏

    开发项目时,为了是代码层次清晰.美观,常常需要调整多行,使之对齐.在网上也看到一些方法,感觉不好用,偶尔发现一个小技巧. (1)多行代码同时右移 同时选中几行,按"Tab"键,就会 ...

  8. 【Xamarin挖墙脚系列:代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧(转)】

    正愁如何选择构建项目中的视图呢,现在官方推荐画板 Storybord...但是好像 xib貌似更胜一筹.以前的老棒子总喜欢装吊,用代码写....用代码堆一个HTML页面不知道你们尝试过没有.等页面做出 ...

  9. 10个小技巧助您写出高性能的ASP.NET Core代码

    今天这篇文章我们来聊一聊如何提升并优化ASP.NET Core应用程序的性能,本文的大部分内容来自翻译,当然中间穿插着自己的理解,希望对大家有所帮助!话不多说开始今天的主题吧! 我们都知道性能是公共网 ...

随机推荐

  1. T-SQL Part XII: Access Remote SQL Server

    要链接远程的SQL Server,需要一下几个步骤(以下的步骤都是在远程系统上进行): 确认远程SQL Server所监听的端口号 官方的文档是使用SQL Server Configuration M ...

  2. Mybatis动态SQL(where元素、set元素、if元素)

    Mybatis动态SQL(where元素.set元素.if元素) - where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句.而且,若语句的开头为“AND”或 ...

  3. php相关知识(一)

    php是服务器端脚本语言.可以生成动态页面内容,可以对数据库中的数据库进行编辑. php变量以$符号开始,后面是变量名,变量名以字母或下划线开始,变量名不能包含空格,变量名区分大小写. php的数据类 ...

  4. django_4数据库2——表外键

    表关系: many to one many to many one to one many to one 记录是如何创建出来的?      先创建one,在在创建many,创建时加入ForeignKe ...

  5. .NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端

    .NET Core love gRPC 千呼万唤的 .NET Core 3.0 终于在 9 月份正式发布,在它的众多新特性中,除了性能得到了大大提高,比较受关注的应该是 ASP.NET Core 3. ...

  6. GitHub远程库的搭建以及使用

    GitHub远程库的搭建 一).配置SSH 步骤: 1).注册GitHub账号 2).本地git仓库与远程的GitHub仓库的传输要通过SSH进行加密 3).创建SSH key ​ 1.检查在用户主目 ...

  7. 《Java基础教程》第一章学习笔记

    Java 是什么呀! 计算机语言总的来说分成机器语言,汇编语言,高级语言.其中Java一种高级计算机语言,它是一种可以编写跨平台应用软件,完全面向对象的程序设计语言. Java划分为三个技术平台,Ja ...

  8. 2019-9-28:渗透测试,基础学习,DNS投毒

    该文章仅供学习,利用方法来自网络文章,仅供参考 DNS劫持 目标机:虚拟机下的win7系统 目标ip:192.168.20.131 目标:使用ettercap进行apr投毒,对win7系统就行,DNS ...

  9. 题解 P1047 【校门外的树】

    可以直接模拟,用珂朵莉树是不有点小题大做. 你怎么做珂朵莉都会骂你:"这么简单的模拟都要用***" 附赠珂朵莉照片一张 另外讲几点: 可以用int,你要不怕MLE #include ...

  10. Java基础面试题及答案(二)

    容器 18. java 容器都有哪些? 常用容器的图录: 19. Collection 和 Collections 有什么区别? java.util.Collection 是一个集合接口(集合类的一个 ...