C++語法小技巧

自為風月馬前卒發表於2018-10-16

前言

寫的很亂,各種內容都有。僅僅是為了記錄一下

而且內容極其不嚴謹(沒錯,只有實踐,沒有理論)!請各位謹慎駕駛!

強制內聯

#define Inline __inline__ __attribute__((always_inline))

本地測試結果:

  • 開O2之後inline和Inline加不加沒啥用

  • 不開O2時inline可能會有負優化,而Inline會讓程式快很多

當然也可以強制不inline

直接在函式名前加

__attribute__((noinline))

利用位運算實現大小寫轉化

可以這麼寫

char ToUpper(char a) {return (a >= `a` && a <= `z`) ? a ^ ` ` : a;}

實測比c++內建的toupper快6倍。。

enum型別

這玩意兒叫“列舉”

格式如下:

enum [enumeration name] {enumerator1[=value1], enumerator2[=value2], ...};

其中,第二個變數的取值預設是第一個變數取值+1,第一個預設是0,當然也可以自己設定

一個簡單的栗子

enum NOIP {a, b, c, d = 22};
cout << c << " " << d;

將會輸出2 22

自定義輸入輸出流

這部分有點硬核啊。。

一個簡單的栗子是這樣的

#include<bits/stdc++.h>
using namespace std;
class Pair {
private: 
    int id;
    string s;
public:
    friend ostream& operator << (ostream& os, Pair& a) {
        os << a.s << ":" << a.id << "
";
        return os;      
    }
    friend istream& operator >> (istream& is, Pair& a) {
        is >> a.s >> a.id;
        return is;      
    }
};
int main( ) {
    Pair a;
    cin >> a;
    cout << a;
    return 0;
}
//input: abc 123
//output : abc:123

注意這裡我們實際上還是在用cin / cout輸入輸出

輸入輸出流在OI中常常應用於輸入輸出優化。

struct InputOutputStream {
    enum { SIZE = 1000001 };
    char ibuf[SIZE], *s, *t, obuf[SIZE], *oh;

    InputOutputStream() : s(), t(), oh(obuf) {}
    ~InputOutputStream() { fwrite(obuf, 1, oh - obuf, stdout); }

    inline char read() {
        if (s == t) t = (s = ibuf) + fread(ibuf, 1, SIZE, stdin);
        return s == t ? -1 : *s++;
    }

    template <typename T>
    inline InputOutputStream &operator>>(T &x) {
        static char c;
        static bool iosig;
        for (c = read(), iosig = false; !isdigit(c); c = read()) {
            if (c == -1) return *this;
            iosig |= c == `-`;
        }
        for (x = 0; isdigit(c); c = read()) x = x * 10 + (c ^ `0`);
        if (iosig) x = -x;
        return *this;
    }

    inline void print(char c) {
        if (oh == obuf + SIZE) {
            fwrite(obuf, 1, SIZE, stdout);
            oh = obuf;
        }
        *oh++ = c;
    }

    template <typename T>
    inline void print(T x) {
        static int buf[23], cnt;
        if (x != 0) {
            if (x < 0) print(`-`), x = -x;
            for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 | 48;
            while (cnt) print((char)buf[cnt--]);
        } else print(`0`);
    }

    template <typename T>
    inline InputOutputStream &operator<<(const T &x) {
        print(x);
        return *this;
    }
} io;

template

template,中文名:模板

分為兩類,一種叫類别範本,一種叫函式模板

類别範本我用的不多

函式模板用的多一些

下面是一個求最大值的模板,c++的標準庫中也是這麼實現的,因此同時存在的話會引起CE

template <typename T>
inline T const& max(T const &a, T const &b) {
    return a > b ? a : b;
}

如果直接呼叫的話,當(a, b)的型別不同時會引起CE。

這時可以直接強制型別轉化

    int a = 1e9;
    long long b = 1e18;
    long long c = max<int>(a, b);
//the output is 1e9

    int a = 1e9;
    long long b = 1e18;
    long long c = max<long long>(a, b);
//the output is 1e18

預編譯黑科技

第一條是強制開棧空間

後面的並不清楚在幹啥,貌似可以強制(O_2)

#pragma comment(linker, "/STACK:102400000,102400000") 
#pragma GCC diagnostic error "-std=c++11"
#pragma GCC optimize("-fdelete-null-pointer-checks,inline-functions-called-once,-funsafe-loop-optimizations,-fexpensive-optimizations,-foptimize-sibling-calls,-ftree-switch-conversion,-finline-small-functions,inline-small-functions,-frerun-cse-after-loop,-fhoist-adjacent-loads,-findirect-inlining,-freorder-functions,no-stack-protector,-fpartial-inlining,-fsched-interblock,-fcse-follow-jumps,-fcse-skip-blocks,-falign-functions,-fstrict-overflow,-fstrict-aliasing,-fschedule-insns2,-ftree-tail-merge,inline-functions,-fschedule-insns,-freorder-blocks,-fwhole-program,-funroll-loops,-fthread-jumps,-fcrossjumping,-fcaller-saves,-fdevirtualize,-falign-labels,-falign-loops,-falign-jumps,unroll-loops,-fsched-spec,-ffast-math,Ofast,inline,-fgcse,-fgcse-lm,-fipa-sra,-ftree-pre,-ftree-vrp,-fpeephole2",3)
#pragma GCC target("avx","sse2")

__builtin系列

  • __builtin_popcount(unsigned int n)

計算(n)的二進位制表示中有多少個1

  • __builtin_parity(unsigned int n)

判斷(n)的二進位制表示中1的個數奇偶性(要你何用?)

  • __builtin_ffs(unsigned int n)

判斷(n)的二進位制末尾最後一個1的位置,從1開始

  • __builtin_ctz(unsigned int n)

判斷(n)的二進位制末尾(0)的個數

  • __builtin_clz(unsigned int n)

判斷(n)的二進位制前導0的個數

指標的騷操作

通過指標實現負下標陣列

#include<bits/stdc++.h>
using namespace std;
int main() {
    int __a[21];
    for(int i = 0; i <= 20; i++) __a[i] = i;
    int *const a = &__a[10];
    printf("%d %d %d", a[7], a[0], a[-7]);
}

相關文章