文章目录
- 1. 移动赋值
- 2. 新的类的功能
- 移动构造
- 移动赋值
- default
- delete
- 3.可变参数模板
- 可变参数包的解析
文章目录
- 1. 移动赋值
- 2. 新的类的功能
- 移动构造
- 移动赋值
- default
- delete
- 3.可变参数模板
- 可变参数包的解析
1. 移动赋值

C++11中,string中的operator= 包含 参数为右值的版本

C++98中 没有移动赋值和移动构造 ,只有参数为左值 的赋值重载(operator=)和拷贝构造


本来只有两次深拷贝,但是由于调用拷贝赋值时,内部又进行一次拷贝构造,所以导致最终进行三次深拷贝
这里编译器是不能优化的,因为优化的前提是 连续的构造或者拷贝构造

正常来说,str作为局部变量,应该作为左值,但编译器会对其优化,通过使用move函数,其函数返回值为右值,所以会先发生移动构造
临时对象 本身就是看不见 摸不到的,所以取不到地址,它也是右值
所以又会发生 移动赋值

移动赋值,实际上也是进行资源的转移

如:将临时对象所指向的数据 转移到s1 中,同时可将废弃数据放入临时对象(将亡值)中
2. 新的类的功能
C++11中新增 了 移动构造函数和 移动赋值运算符重载
移动构造
若没有实现移动构造,并且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个
(若实现了其中任意一个,则说明是深拷贝的类,如何转移应该自己说了算)
编译器就会自动生成一个默认移动构造
默认生成的移动构造,
对于内置类型成员,会执行浅拷贝(按字节拷贝)
对于自定义类型成员,则看这个成员是否实现移动构造,
若实现了就调用移动构造,若没有实现就调用拷贝构造

person类中,既没有实现移动构造 ,也没有实现析构函数、拷贝构造、拷贝赋值重载
所以该类会自动生成一个默认的移动构造
对于内置类型成员 _age,拷贝构造与 移动构造 都是完成浅拷贝

对于自定义类型成员 _name,因为在yzq命名空间的string类中存在 移动构造,所以调用 其移动构造
刚调试执行到s1时,s3实际上空间为空
当调试执行到s3时,对于内置类型成员_age 进行浅拷贝 ,所以s3._age 也被置为19
对于 自定义类型 成员 _name,因为string类中存在 移动构造,所以调用移动构造(资源转移)
所以 s1._name 空间被置空,s3._name 指向原s1._name的空间的地址
移动赋值
移动赋值与上述的移动构造类似
若没有实现移动赋值,并且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个
(若实现了其中任意一个,则说明是深拷贝的类,如何转移应该自己说了算)
编译器就会自动生成一个默认移动赋值
默认生成的移动赋值,
对于内置类型成员,会执行浅拷贝(按字节拷贝)
对于自定义类型成员,则看这个成员是否实现移动赋值,
若实现了就调用移动赋值,若没有实现就调用拷贝赋值
刚开始时,s4实际上空间为空
调试到移动赋值时,对于内置类型成员_age 进行浅拷贝 ,所以s4._age 也被置为19
对于 自定义类型 成员 _name,因为string类中存在 移动赋值,所以调用移动赋值(资源转移)
所以 s1._name 空间被置空,s4._name 指向原s1._name的空间的地址
default
强制生成默认函数的关键字 -default

由于显示写析构,使其无法生成默认的移动赋值,影响自定义类型成员 _name 移动赋值变成深拷贝

通过 default 强制生成默认移动赋值,即使有显示的析构函数存在,也不影响 自定义类型成员 _name 的移动赋值
delete
禁止生成默认函数的关键字 delete

istream在C++11中,不期望被拷贝,(拷贝会涉及缓冲区等问题)

默认成员函数,如果不写会默认生成,加入delete后可禁止生成
3.可变参数模板
可变参数模板 :可以接受可变参数的函数模板和类模板

声明一个参数包Args…args,这个参数包中包含0到任意个模板参数

参数是不限制类型和个数的
可变参数包的解析
通过增加一个模板参数,让编译器去解析参数包的东西
应用递归推导思维

主函数中的test是无参的,所以调用无参的test函数

当有一个参数a是,将a传给test作为第一个参数val,而test的第二个参数作为参数包就没有了
(参数包可以包含0个参数)
在带有形参的test函数中调用无参的test函数,进行换行

当有两个参数a和b时,将a传给test作为第一个参数val,将b传给test作为第二个参数 参数包
当test函数内部再次调用 test时,由于 参数包中的参数不为0,所以再次调用 带参的test
将b传给新的test作为第一个参数val , 新的test的第二个参数 参数包为0
当test函数内部再次调用 test时,由于参数包参数为0,所以去调用 无参的test ,进行换行