C++ 代碼小技巧(一)

 

在寫代碼的時候,咱們經常會用一些小技巧,下面作簡單介紹node

1、o1+o2+o3(常數優化)

如題,開優化開關。ios

有的OJ上有O2優化選項,固然,你也能夠這樣:在代碼開頭這樣加一句:ide

#pragma GCC optimize("O1")
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
o1+o2+o3

 

(逃~函數

Tips:此方法對STL很是有效!(NOIP賽場上我不知道能不能用,建議不要用)優化

2、 inline 關鍵字(常數優化)

能夠在一個函數的最開始加上inline,如:spa

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

 

意義:在編譯時,把這個函數放到使用它的地方,如:3d

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 0;                            
}        
inline example

 

使用貼士:code

  1. 不要試圖給遞歸函數加inline,這樣可能會更慢!
  2. 不要試圖給調用屢次且代碼量很大(即較複雜) 的非遞歸函數加inline, 這樣並不會優化!
  3. 本方法應該給調用屢次或複雜度較低的函數使用(如:min, max, fast_IO相關函數)。

3、register 關鍵字(常數優化)

能夠在一個變量聲明的類型前面加上這個關鍵字。例:blog

// example #1: 
register int a;
// example #2: 
register long long b[10007];
// 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

4、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的類型!

5、fread大招

先給代碼嚶嚶嚶

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

 

說明:

  1. fread比getchar快,因此用fread優化程度更高
  2. 若本地運行且不加freopen,那麼會出錯(無休止的讀入)!(由於fread會讀滿1 << 15個字節,而從文件讀入時會讀到文件結束符從而中止讀入,不會出問題)
  3. 不知道fread能夠經過這篇文章簡要了解一下

6、快讀整數(fast_IO #1

代碼仍是很簡單的,以下:

template <typename _TpInt>
inline _TpInt read()       
{
    register int flag = 1;
    register char c = Getchar();
    while ((c > '9' || c < '0') && c != '-') 
        c = Getchar();
    if (c == '-') flag = -1, c = Getchar();
    register _TpInt init = (c & 15);
    while ((c = Getchar()) <= '9' && c >= '0') 
        init = (init << 3) + (init << 1) + (c & 15);
    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

 

7、快讀實數(fast_IO #2

仿照整數快讀,寫出實數快讀:

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

 

沒什麼好說明的。

應用例子:

float d;
double e;
d = readr<float>();
e = readr<double>();
fast_IO #2 example

 

8、快寫整數(fast_IO #3

使用遞歸執行。

template <typename _TpInt>
inline void write(_TpInt x)
{
    if (x < 0) {
        putchar('-');
        write<_TpInt>(~x + 1);
    }
    else {
        if (x > 9) write<_TpInt>(x / 10);   
        putchar(x % 10 + '0');
    }
}
fast_IO #3

 

 

說明:

  1. (~x+1) = -x,此處是爲了unsigned型整數而寫此句
  2. 若去掉 if (x > 9),則會死循環
  3. 本函數不可用於輸出某種有符號類型的最小數!會無限輸出負號!!!e.g.
    • write<int>(-2147483648);
    • write<short>(-65536);
    • etc...

應用例子:

write<int>(1);
printf("\n");
write<short>(-891);
printf("\n");
write<int>(-2147483647);
printf("\n");
long long n = 6;
write<long long>(n);
printf("\n");
fast_IO #3 example

 

尾聲:給個模板吧

 1 // luogu-judger-enable-o2
 2 /*
 3     Problem: C++ 代碼模板 
 4     Author: 航空信奧 
 5     Date: 2018/08/02
 6 */
 7 #pragma GCC optimize("O1")
 8 #pragma GCC optimize("O2")
 9 #pragma GCC optimize("O3")
10 #include <stdio.h>
11 #include <iostream>
12 #include <string.h>
13 #include <vector>
14 #include <map>
15 #include <set>
16 #define lowbit(a) ((a) & (~a + 1)) // define 快 
17 using namespace std;
18 namespace AuthorName { // 防重名 
19     inline char Getchar();
20     template <typename _TpInt> inline _TpInt read();
21     template <typename _TpRealnumber> inline double readr();
22     template <typename _TpInt> inline void write(_TpInt x);
23     template <typename _TpSwap> inline void swap(_TpSwap &x, _TpSwap &y);
24 
25     int main()
26     {
27         // here : DO SOMETHING
28         return 0;
29     }
30 
31     char BufferRead[1 << 15];
32     int rLen = 0, rPos = 0;
33     inline char Getchar()
34     {
35         if (rPos == rLen) rPos = 0, rLen = fread(BufferRead, 1, 1 << 15, stdin);
36         if (rPos == rLen) return EOF;
37         return BufferRead[rPos++];
38     } 
39 
40     template <typename _TpInt>
41     inline _TpInt read()       
42     {
43         register int flag = 1;
44         register char c = Getchar();
45         while ((c > '9' || c < '0') && c != '-') 
46             c = Getchar();
47         if (c == '-') flag = -1, c = Getchar();
48         register _TpInt init = (c & 15);
49         while ((c = Getchar()) <= '9' && c >= '0') 
50             init = (init << 3) + (init << 1) + (c & 15);
51         return init * flag;
52     }
53 
54     template <typename _TpRealnumber>
55     inline double readr()       
56     {
57         register int flag = 1;
58         register char c = Getchar();
59         while ((c > '9' || c < '0') && c != '-') 
60             c = Getchar();
61         if (c == '-') flag = -1, c = Getchar();
62         register _TpRealnumber init = (c & 15);
63         while ((c = Getchar()) <= '9' && c >= '0') 
64             init = init * 10 + (c & 15);
65         if (c != '.') return init * flag;
66         register _TpRealnumber l = 0.1;
67         while ((c = Getchar()) <= '9' && c >= '0') 
68             init = init + (c & 15) * l, l *= 0.1;
69         return init * flag;
70     }
71 
72     template <typename _TpInt>
73     inline void write(_TpInt x)
74     {
75         if (x < 0) {
76             putchar('-');
77             write<_TpInt>(~x + 1);
78         }
79         else {
80             if (x > 9) write<_TpInt>(x / 10);   
81             putchar(x % 10 + '0');
82         }
83     }
84 
85     template <typename _TpSwap>
86     inline void swap(_TpSwap &x, _TpSwap &y)
87     {
88         _TpSwap t = x;
89         x = y;
90         y = t;
91     }
92 }
93 
94 int main()
95 {
96     AuthorName::main();
97     return 0;
98 }
View Code
相關文章
相關標籤/搜索