C++笔记-C++11(三)
会⽣成⼀个默认的。C++11 新增了两个默认成员函数,移动构造函数和移动赋值运算符重载。
如果你没有⾃⼰实现移动构造函数,且没有实现析构函数 、拷⻉构造、拷⻉赋值重载中的任意⼀
个。那么编译器会⾃动⽣成⼀个默认移动构造。默认⽣成的移动构造函数,对于内置类型成员会执
⾏逐成员按字节拷⻉,⾃定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调⽤
移动构造,没有实现就调⽤拷⻉构造。
上面看着有三个函数,但是我们之前也说过这三个函数一般都是同时出现的,出现析构函数,说明这个类中有资源需要释放,自然就要写拷贝构造和拷贝赋值,变相地降低了我们的记忆成本。
下面我们来看一个例子:
前面两个例子我就不多说了,主要看最后一个,此时在Person类中我们并没有实现 析构函数 、拷⻉构造、拷⻉赋值重载中的任何一个,此时就会生成默认的移动构造函数去调用string类中的移动构造函数。
结果也正如我们所言,确实调用了string的移动构造。
而如果写了三个函数中的一个,比如我上面写的拷贝构造函数,那么就不会生成默认的移动构造函数,而是会走Person类中的拷贝构造,进而去调用string中的拷贝构造,结果也证实了这句话,确实没有调用string中的移动构造,而是调用了拷贝构造。
移动赋值和移动构造一样,在没有三个函数时会去调用相应的移动赋值。
相应的有这三个函数中的任意一个,也就不会生成默认移动赋值,会去调用相应的拷贝赋值。
5.2成员变量声明时给缺省值
成员变量声明时给缺省值是给初始化列表⽤的,如果没有显⽰在初始化列表初始化,就会在初始化列表⽤这个缺省值初始化,这点我们在类和对象就已经讲过,这里就不过多赘述了。
5.3default和delete
C++11可以让你更好的控制要使⽤的默认函数。假设你要使⽤某个默认的函数,但是因为⼀些原因
这个函数没有默认⽣成。⽐如:我们提供了拷⻉构造,就不会⽣成移动构造了,那么我们可以使⽤
default关键字显⽰指定移动构造⽣成。
我们来看一个例子:
和上面一样,此时我们运行就如上图所示,只会调用拷贝构造函数,那么我们要想让其调用相应的移动构造呢?
我们上面讲的生成默认的移动构造是一个办法,那么还有什么办法呢?
如上图所示,我们可以利用default关键字来强制生成一个Person类的移动构造函数,这样也能调用string中的移动构造。
而default的作用也就体现出来了,就是强制生成一个函数,当然不局限于上面的移动构造,可以时构造函数等等。
而delete与它正好相反,不让编译器强制生成某个函数:
就比如输入输出流,我们可以看到,在ostream中是不允许生成拷贝构造函数的,因为如果能拷贝构造会出现很多复杂的问题。
6.lambda
6.1lambda表达式语法
lambda 表达式本质是⼀个匿名函数对象,跟普通函数不同的是他可以定义在函数内部。lambda 表达式语法使⽤层⽽⾔没有类型,所以我们⼀般是⽤auto或者模板参数定义的对象去接收 lambda 对象。
我们之前还学过的函数指针,仿函数也都是可调用对象,现在又多了一种lambda。
lambda表达式的格式: [capture-list] (parameters)-> return type {function boby }。
capture-list: 捕捉列表,该列表总是出现在 lambda 函数的开始位置,编译器根据[]来 判断接下来的代码是否为 lambda 函数,捕捉列表能够捕捉上下⽂中的变量供 lambda 函数使 ⽤,捕捉列表可以传值和传引⽤捕捉,具体细节7.2中我们再细讲。捕捉列表为空也不能省略。
parameters: 参数列表,与普通函数的参数列表功能类似,如果不需要参数传递,则可以连
同()⼀起省略。
-> return type: 返回值类型,⽤追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。⼀般返回值类型明确情况下,也可省略,由编译器对返回类型进⾏推导。{function boby }: 函数体,函数体内的实现跟普通函数完全类似,在该函数体内,除了可以使⽤其参数外,还可以使⽤所有捕获到的变量,函数体为空也不能省略。
