zoukankan      html  css  js  c++  java
  • C++ 代码小技巧(一)

     

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

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

    使用贴士:

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

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

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

    // 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

    四、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[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可以通过这篇文章简要了解一下

    六、快读整数(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

    七、快读实数(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

    八、快写整数(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("
    ");
    write<short>(-891);
    printf("
    ");
    write<int>(-2147483647);
    printf("
    ");
    long long n = 6;
    write<long long>(n);
    printf("
    ");
    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
  • 相关阅读:
    Objective-C ,ios,iphone开发基础:ios数据库(The SQLite Database),使用终端进行简单的数据库操作
    Objective-C ,ios,iphone开发基础:picker控件详解与使用,(实现省市的二级联动)
    Objective-C ,ios,iphone开发基础:多个视图(view)之间的切换2,使用导航栏控制,以及视图之间传值。
    Objective-C ,ios,iphone开发基础:多个视图(view)之间的切换,以及视图之间传值。
    Objective-C ,ios,iphone开发基础:NSDictionary(字典) 和 NSMutableDictionary
    Objective-C ,ios,iphone开发基础:几个常用类-NSString
    为MYPoint类写一个分类
    使用copy再次实现Circle类,保证不能有内存泄漏问题
    实现Square类,让其继承自Rectangle类,并在Square类增添新属性和方法,在2的基础上,在Square类中重写Rectangle类中的初始化和打印方法
    实现Square类,让其继承自Rectangle类,并在Square类增添新属性和方法
  • 原文地址:https://www.cnblogs.com/hkxadpall/p/9497900.html
Copyright © 2011-2022 走看看