I learned something today: C++ (part I)
Learn . Modern C++
最近在读一本名叫“C++ High Performance”的书,觉得有一定帮助,学习了一点现代的C++,故记录。
Automatic type deduction: the auto keyword
In function signatures
可以使用auto
来标识函数返回值类型,例如以下表达式:
1 | // Return type: value |
In variables
在声明变量时使用auto
,会令人产生一种正在使用某些动态类型语言的错觉,例如:
1 | auto i = 0; |
使用了auto
关键字后,我们可以不用担心自己是否使用了正确的变量类型,但我们仍需决定,我们想要的是reference 还是copy,以及变量是只读还是需要修改,如果是只读,最好显式的表明,例如使用 const auto&
。
The lambda function
Basic syntax
1 | using namespace std; |
The capture block
Lambda function 的小括号里是参数,花括号里是函数语句,这些和一般的函数是一样的,多出来的方括号为capture block
1 | auto count_above(const std::vector<int>& vals, int th) { |
以上代码中,参数th被capture block “捕获”,复制进了lambda function 内,从而可以灵活的改变is_above函数要比较的值。当然capture block 中也可以放reference。
1 | int t = 0; |
上面的lambda 与下面定义的这个类相似。但是每一个Lambda 的类型都是不同的,即使他们一毛一样。
1 | int t = 0; |
我们也可以在capture block里的初始化变量,可以看做在类里初始化成员变量一般。但是我们不能在普通的lambda 里更改capture block 所capture 的变量,原因可以在上面看到:对应类的唯一一个成员函数是用const标记的。要使得我们能够更改capture的变量,需要加上mutable
这一modifier,或是一开始就传递引用。
1 | auto func = [&t](int b){ |
通过使用[=]
or [&]
,我们可以无脑的capture当前可用的所有变量,[=]
意味着“captures all by value”,而[&]
意味着“captures all by reference”。当然,我们并不是真正的把所有变量都被复制到了lambda内,只有我们实际用了的变量会真正地被复制。我们也可以指定个别变量的捕捉方式,如下
1 | int a, b, c; |
Lambdas and std::function
1 | std::function< return_type ( parameter0, parameter1...) > |
如果我们的lambda有和某个std::function
相同的返回类型且接收相同的参数类型,那么该lambda就可以装入该std::function
中,以下为实际使用例子,实现了类似策略模式的感觉:
1 | using namespace std; |
然而,相比直接用lambda,使用std::function
付出的代价更大, 无论是从时间上还是空间上考虑。