C++中的一些小Tricks

转载自`https://codeforces.com/blog/entry/15643`

Posted by AspenStars on December 3, 2019

本文转载自codeforces

1.直接用{}赋值

对pair和常见的容器都适用,不适用于stackqueue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
pair<int, int> p;
p = {3, 4};

pair<int, pair<char, long long> > p;
p = {3, {'a', 8ll}};

vector<int> v;
v = {4, 5};

deque<vector<pair<int, int>>> d;
//此处jekyll有Bug,不能正确显示{},自行将外面的两层()换成{}
d = (({3, 4}, {5, 6}), ({1, 2}, {3, 4}));

set<int> s;
s = {4, 6, 2, 7, 4};

list<int> l;
l = {5, 6, 9, 1};

array<int, 4> a;
a = {5, 8, 9, 2};

tuple<int, int, char> t;
t = {3, 4, 'f'};

2.在宏中命名参数

可以使用“#”符号获取传递给宏的参数的名称
比如参数叫a_variable,值为376,调用what_is(x)函数,输出a_variable is 376

1
2
3
4
5
6
7
#define what_is(x) cerr << #x << " is " << x << endl;
// ...
int a_variable = 376;
what_is(a_variable);
// prints "a_variable is 376"
what_is(a_variable * 2 + 1)
// prints "a_variable * 2 + 1 is 753"

3.摆脱include

使用#include <bits/stdc++.h>

这个库包括许多在比赛中需要的库,比如algorithm, iostream, vector等等。相信我,你不需要包括任何其他东西!

4.隐函数(并非真的隐藏,只是用得少)

可以当做调用函数一样直接调用

1
2
3
t = __gcd(18, 27);
printf("%d",t);
// prints "9"
  1. __gcd(value1, value2)
    此函数返回两个数字的gcd
    不需要为gcd函数编写欧几里德算法。
    __gcd(18, 27) = 9
  2. __builtin_ffs(x)
    返回右起第一个‘1’的位置
    这个函数返回x的二进制形式下最低位1的位置索引值+1x==0返回0。
    这里x是int类型。this function with suffix ‘l’ gets a long argument and with suffix ‘ll’ gets a long long argument.
    例如,由于10在2进制中是“…1010”,从右开始的第一个1位在索引1处(从0开始),所以函数返回1+索引,所以__builtin_ffs(10) = 2

  3. __builtin_clz(x)
    返回左起第一个‘1’之前0的个数
    __builtin_clz(16) = 27,因为16的二进制表示为’ … 10000’,左起第一个1在第5位. 而无符号整数型(unsigned int)为32位. 所以函数返回32 — 5 = 27.

  4. __builtin_ctz(x)
    返回右起第一个‘1’之后的0的个数
    __builtin_ctz(16) = 4 因为16的二进制表示为’ … 10000’

  5. __builtin_popcount(x)
    返回‘1’的个数
    __builtin_popcount(14) = 3,因为14的二进制表示为’… 111 0’有3个二进制的1.

5.可变参数函数和宏

1
2
3
4
5
6
7
8
9
10
#define a_macro(args...) sum(args)
int sum() { return 0; }
template<typename T, typename... Args>
T sum(T a, Args... args) { return a + sum(args...); }

int main() { 
    cout << sum(5, 7, 2, 2) + sum(3.14, 4.89); 
    /* prints "24.03" */ 
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <bits/stdc++.h>

using namespace std;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

int main() {
	int a = 4, b = 8, c = 9;
	error(a, b, c);
}
1
2
3
4
Output:
a = 4
b = 8
c = 9

C++11新特性

1
2
3
4
set<int> s = {8, 2, 3, 1};
for (auto it: s)
    cout << it << ' ';
// prints "1 2 3 8"

可以将auto换成auto &

1
2
3
4
5
6
vector<int> v = {8, 2, 3, 1};
for (auto &it: v)
    it *= 2;
for (auto it: v)
    cout << it << ' ';
// prints "16 4 6 2"