Rvalue references

Rvalue-references

Rvalue references are a new reference type introduced in C++0x that help solve the problem of unnecessary coping and enable perfect forwarding. When the right-hand side of an assignment is an rvalue, then the left-hand side object can steal resources from the right-hand side object rather than performing a seperate allocation, thus enabling move semantics.

Lvalue: 可以出现于 operator = 左侧者

Rvalue: 只能出现于 operator = 右侧者

只要在内存中有确定存储空间的都是左值。

查看更多

lambda

C++11 introduced lambdas, allowing the definition of inline functionality, which can be used as a parameter or a local object. Lambdas change the way the C++ statndard library is used.

A lambda is a definition of functionality that can be defined inside statements and expressions. Thus, you can use a lambda as an inline function. The minimal lambda function has no parameters and simply does something.

1
2
3
4
5
6
7
8
9
10
11
12
13
[] {
std::cout << "hello lambda"<<std::endl;
}

[] {
std::cout<< "hello lambda"<<std::endl;
}();

auto l = [] {
std::cout<< "hello lambda"<<std::endl;
}

l();

查看更多

decltype

Defines a type equivalent to the type of an expression.

By using the decltype keyword, you can let the compiler find out the type of an expression, this is the realization of the often requested typepf feature.

One application of decltype is to declare return types; Another is to use it in metaprogramming or to pass the type of a lambda.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 1. declare return types
template<typename T1, typename T2>
decltype(x + y) add(T1 x, T2 y); // 不行

template<typename T1, typename T2>
auto add(T1 x, T2 y) -> decltype(x + y);

// 2. meta programming
template<typename T>
void test_decltype(T obj) {
map<string, float>::value_type elem1;
map<string, float> coll;
decltype(coll)::value_type elem2;

typedef typename decltype(obj)::iterator iType; // => typedef typename T::iterator iType
// test_decltype(complex<int>()) 编译失败

decltype(obj) anotherObj(obj);
}

// 3. pass the type of lambda
auto cmp = [](const Person& p1, const Person& p2) {
return p1.lastname() < p2.lastname() || (p1.lastname() == p2.lastname() && p1.firstname() < p2.firstname());
};
std::set<Person, decltype(cmp)> coll(cmp);

Type Alias & using

Type alias

Similar to typedef

1
2
3
4
5
6
7
8
9
10
11
// type alias, identical to
// typedef void (*func)(int, int)

using func = void (*)(int, int);

void example(int, int) {}
func fn = example;

// alias template
template<class CharT> using mystring = std::basic_string<CharT, std::char_traits<CharT>>;
mystring<char> str;

和 <string_fwd.h> 都有以下 typedef:

typedef basic_string string;

1
2
3
4
5
6
7
8
9
10
// type alias can introduce a member typedef name
template<typename T>
struct Container {
using value_type = T; // typedef T value_type;
};

template<typename Cntr>
void fn2(const Cntr& c) {
typename Cntr::value_type n;
}

查看更多

Range-based for statement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
for( decl : coll) {
statement
}
*/
for(int i: {2345676788}) {
cout<<i<<endl;
}

vector<double> vec;
for(auto elem: vec) {
cout<< elem <<endl;
}

for(auto& elem: vec) {
elem *= 3;
}// 关联式容器不能修改值

No explicit type conversions are possible when elements are initialized as decl inside the for loop. Thus, the following does not compile:

1
2
3
4
5
6
7
8
9
10
class C {
public:
explicit C(const string& s);
....
};

vector<string> vs;
for(const C& elem: vs) { // error no conversion from string to C defined
cout<<elem<<endl;
}

explicit关键字

用在一个实参上的 explicit。

1
2
3
4
5
6
7
8
9
struct Complex {
int real, imag;
Complex(int re, int im = 0): real(re), imag(im){}
Complex operator+(const Complex& x) {
return Complex((real + x,real), (imag + x.imag));
}
}
Complex c1(12, 5);
Complex c2 = c1 + 5; // 会调用构造函数 将 5 隐式转换为 Complex
1
2
3
4
5
6
7
8
9
struct Complex {
int real, imag;
explicit Complex(int re, int im = 0): real(re), imag(im){}
Complex operator+(const Complex& x) {
return Complex((real + x,real), (imag + x.imag));
}
}
Complex c1(12, 5);
Complex c2 = c1 + 5; // [Error] no match for 'operator+'(operand types are 'Complex' ands 'int')

用在多个实参上的 explicit

Variadic Templates

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>

// 处理无参数的情况
void printX() {
std::cout << std::endl;
}

// 任意参数类型
template<typename T, typename... Types>
void printX(const T& firstArg, const Types&... args) {
std::cout << firstArg << std::endl;
std::cout << "left:" << sizeof...(args) << "params" << " ";
// args 会被分为2部分 一部分是第一个参数 第二部分是args...
printX(args...);
}

// ... 是所谓的 pack
// 用于 template parameters 就是 template parameters pack
// 用于 function parameter types 就是 function parameter types pack
// 用于 function parameters 就是 function parameters pack

void printf(const char *s) {
while(*s) {
if(*s=='%'&&*(++s)!='%')
throw std::runtime_error("invalid format string");
std::cout << *s++;
}
}

//printf
template<typename T, typename... Args>
void printf(const char* s, T value, Args... args) {
while(*s) {
if(*s=='%'&&*(++s)!='%') {
std::cout << value;
printf(++s, args...);
return;
}
std::cout << *s++;
}
throw std::runtime_error("invalid format string");
}

int maximum(int n) {return n;}

template<typename...Args>
int maximum(int n, Args... args) {
return std::max(n, maximum(args...));
}

int main() {
printX(1,2,3,"asa");
std::cout << maximum(1,2,3,4) << std::endl;
}

uniform initialization

1
2
3
4
5
6
int values[] {1,2,3};
vector<int> v{2,3,5,6,7,11,13};
vector<string> cities {
"beijing", "shanghai","nanjing"
};
complex<double> c{4.0, 3.0};

利用一个事实,编译器看到{t1,t2,…,tn} 便会做出一个 initializer_list, 它关联至一个 array<T, n>。 调用函数(例如 ctor)时改 array 内的元素可被编译器分解逐一传给函数。但若函数参数是个 initializer_list, 调用者却不能基于数个 T 参数然后以为他们会被自动转为一个 initializer_list 传入。

1
2
3
4
5
6
7
void print(std::initializer_list<int> vals)
{
for(auto p = vals.begin(); p != vals.end(); ++p) {
std::cout<< *p <<endl;
}
}
print({1,2,3,4,5,6,7,8});

The initializer_list object refers to the elements of this array without containing them: copy initializer_list object produces another object referring to the same underlying elements, not to new copies of them.

查看更多