C++ Tricks

以下内容大部分使用 C++11 !
以下内容大部分使用 C++11 !
以下内容大部分使用 C++11 !

通过 {} 来给容器赋值

pair<int, int> p;
// ...
p = make_pair(3, 4);

其实可以这样

pair<int, int> p;
// ...
p = {3, 4};

对于复杂的 pair

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

对于其他容器(vector,deque,set)

vector<int> v;
v = {1, 2, 5, 2};
for (auto i: v)
    cout << i << ' ';
cout << '
';
// prints "1 2 5 2"


deque<vector<pair<int, int>>> d;
d = {{{3, 4}, {5, 6}}, {{1, 2}, {3, 4}}};
for (auto i: d) {
    for (auto j: i)
        cout << j.first << ' ' << j.second << '
';
    cout << "-
";
}
// prints "3 4
//         5 6
//         -
//	   1 2
//	   3 4
//	   -"


set<int> s;
s = {4, 6, 2, 7, 4};
for (auto i: s)
    cout << i << ' ';
cout << '
';
// prints "2 4 6 7"


list<int> l;
l = {5, 6, 9, 1};
for (auto i: l)
    cout << i << ' ';
cout << '
';
// prints "5 6 9 1"


array<int, 4> a;
a = {5, 8, 9, 2};
for (auto i: a)
    cout << i << ' ';
cout << '
';
// prints "5 8 9 2"


tuple<int, int, char> t;
t = {3, 4, 'f'};
cout << get<2>(t) << '
';

注意:stack,queue不适用

通过 '#' 来得到参数名

#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"

使用 <bits/stdc++.h>

#include <bits/stdc++.h>

库中自带却不怎么常用的函数

  • __gcd(value1,value2)
    e.g. __gcd(18, 27) = 9.
  • __builtin_ffs(x)
    e.g. __builtin_ffs(10) = 2 because 10 is '...10 1 0' in base 2 and first 1-bit from right is at index 1 (0-based) ’and function returns 1 + index.
  • __builtin_clz(x)
    e.g. __builtin_clz(16) = 27 because 16 is ' ... 10000'. Number of bits in a unsigned int is 32. so function returns 32 — 5 = 27.
  • __builtin_ctz(x)
    e.g. __builtin_ctz(16) = 4 because 16 is '...1 0000 '. Number of trailing 0-bits is 4.
  • __builtin_popcount(x)
    e.g. __builtin_popcount(14) = 3 because 14 is '... 111 0' and has three 1-bits.

Note 还有其他 __bultin 函数,但是不怎么常用,cpp

变长参数函数与宏

int sum() { return 0; }

template<typename... Args>
int sum(int a, Args... args) { return a + sum(args...); }

int main() { cout << sum(5, 7, 2, 2) + sum(3, 4); /* prints "23" */ }

不止是 int

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" */ }

C++14 可以用 auto sum(T a, Args... args)

使用宏

#define a_macro(args...) sum(args...)

int sum() { return 0; }

template<typename T, typename... Args>
auto sum(T a, Args... args) { return a + sum(args...); }

int main() { cout << a_macro(5, 7, 2, 2) + a_macro(3.14, 4.89); /* prints "24.03" */ }

=> debug 函数

#include <bits/stdc++.h>

using namespace std;

#define error(args...) { vector<string> _v = split(#args, ','); err(_v.begin(), args); }

vector<string> split(const string& s, char c) {
	vector<string> v;
	stringstream ss(s);
	string x;
	while (getline(ss, x, c))
		v.emplace_back(x);
	return move(v);
}

void err(vector<string>::iterator it) {}
template<typename T, typename... Args>
void err(vector<string>::iterator it, T a, Args... args) {
	cerr << it -> substr((*it)[0] == ' ', it -> length()) << " = " << a << '
';
	err(++it, args...);
}

int main() {
	int a = 4, b = 8, c = 9;
	error(a, b, c);
}
/*
Output:
  a = 4
  b = 8
  c = 9
*/

C++0x 与 C++

遍历

set<int> s = {8, 2, 3, 1};
for (set<int>::iterator it = s.begin(); it != s.end(); ++it)
    cout << *it << ' ';
// prints "1 2 3 8"

上面代码好长呀,可以这样

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

可以用 &auto 来 替代 auto

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

Power of auto

set<pair<int, pair<int, int> > >::iterator
可以这样写 auto it = s.begin()

for(i = 1; i <= n; i++) {
    for(j = 1; j <= m; j++)
        cout << a[i][j] << " ";
    cout << "
";
}

等价于

for(i = 1; i <= n; i++)
    for(j = 1; j <= m; j++)
        cout << a[i][j] << " 
"[j == m];

tie 和 emplace_back

#define mt make_tuple
#define eb emplace_back
typedef tuple<int,int,int> State; // operator< defined

int main(){
  int a,b,c;
  tie(a,b,c) = mt(1,2,3); // assign
  tie(a,b) = mt(b,a); // swap(a,b)

  vector<pair<int,int>> v;
  v.eb(a,b); // shorter and faster than pb(mp(a,b))

  // Dijkstra
  priority_queue<State> q;
  q.emplace(0,src,-1);
  while(q.size()){
    int dist, node, prev;
    tie(dist, ode, prev) = q.top(); q.pop();
    dist = -dist;
    // ~~ find next state ~~
    q.emplace(-new_dist, new_node, node);
  }
}

emplace_backpush_back更快,紧跟末尾比在他处快?
tie 中可以使用 ignore 来忽略值

tuple<int, int, int, char> t (3, 4, 5, 'g');
int a, b;
tie(b, ignore, a, ignore) = t;
cout << a << ' ' << b << '
';

/*
Output:
  5 3
*/

利用宏来循环

#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
  • 不需要指明类型
  • 从 begin 到 end
vector<int> v = {4, 5, 6, 4, 8};
rep(it, end(v), begin(v))
    cout << *it << ' ';
// prints "8 4 6 5 4"

lambda function

[capture list](parameters) -> return value { body }
e.g.

auto f = [] (int a, int b) -> int { return a + b; };
cout << f(1, 2); // prints "3"

可以在 for_each,sort等 STL 中使用

vector<int> v = {3, 1, 2, 1, 8};
sort(begin(v), end(v), [] (int a, int b) { return a > b; });
for (auto i: v) cout << i << ' ';

/*
Output:
  8 3 2 1 1
*/

move 的用法

使用move 来移动容器,不需要 copy

vector<int> v = {1, 2, 3, 4};
vector<int> w = move(v);

cout << "v: ";
for (auto i: v)
    cout << i << ' ';

cout << "
w: ";
for (auto i: w)
    cout << i << ' ';
/*
Output:
  v: 
  w: 1 2 3 4 
*/

C++0x Strings

Raw Strings

string s = R"(Hello, World!)"; // Stored: "Hello, World!"
A raw string skips all escape characters like 
 or ". e.g.

string str = "Hello	World
";
string r_str = R"(Hello	World
)";
cout << str << r_str;

/*
Output:

Hello	World
Hello	World

*/

// You can also have multiple line raw string:

string r_str =
R"(Dear Programmers,
I'm using C++11
Regards, Swift!)";
cout << r_str;

/*
Output:
Dear Programmer,
I'm using C++11
Regards, Swift!
*/

Regular Expressions (regex)

** e.g.** regex r = "[a-z]+";

regex email_pattern(R"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$)"); 
// This email pattern is not totally correct! It's correct for most emails.
string
valid_email("swift@codeforces.com"),
invalid_email("hello world");

if (regex_match(valid_email, email_pattern))
    cout << valid_email << " is valid
";
else
    cout << valid_email << " is invalid
";

if (regex_match(invalid_email, email_pattern))
    cout << invalid_email << " is valid
";
else
    cout << invalid_email << " is invalid
";
/*
Output:

swift@codeforces.com is valid
hello world is invalid
*/

更多资料

户定义数据标识 (User-defined literals)

栗子 0xA,1000ll,3.14f等等

long long operator "" _m(unsigned long long literal) {
	return literal;
}

long double operator "" _cm(unsigned long long literal) {
	return literal / 100.0;
}

long long operator "" _km(unsigned long long literal) {
	return literal * 1000;
}

int main() {
	// See results in meter:
	cout << 250_m << " meters 
"; // Prints 250 meters
	cout << 12_km << " meters 
"; // Prints 12000 meters
	cout << 421_cm << " meters 
"; // Prints 4.21 meters
}

Note 需要添加下划线_
声明如下
[returnType] operator "" _[name]([parameters]) { [body] }
Note 参数仅能使用如下

(const char *)

(unsigned long long int)

(long double)

(char)

(wchar_t)

(char16_t)

(char32_t)

(const char *, size_t)

(const wchar_t *, size_t)

(const char16_t *, size_t)

(const char32_t *, size_t)

原贴
收录整理,以备复习

原文地址:https://www.cnblogs.com/Forgenvueory/p/7352719.html