【C++11】移动赋值 | 新的类功能 | 可变参数模板

2023-10-17 08:59:07 浏览数 (1)

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 ,进行换行

0 人点赞