c++11中的右值引用以及移动构造
2015-11-29 15:47
302 查看
拷贝构造是形参是const对象的引用,不可以修改该引用对象
而移动构造德尔形参是右值引用,可以修改引用对象。
下面是《深入理解c++11》中对拷贝构造和移动构造的对比图,(ps:根据图的拷贝构造,可以看出该拷贝构造是一个深拷贝,成员指向了一个新的内存地址)
以下是自己的实现,看注释
使用右值引用为临时对象 "续命"
利用移动构造和std::move实现高性能的置换swap
而移动构造德尔形参是右值引用,可以修改引用对象。
下面是《深入理解c++11》中对拷贝构造和移动构造的对比图,(ps:根据图的拷贝构造,可以看出该拷贝构造是一个深拷贝,成员指向了一个新的内存地址)
以下是自己的实现,看注释
class Human { public: Human() : mNum(nullptr) { mNum = new int(123); printf("Human 构造\n"); } Human(const Human& _h) { mNum = new int(*_h.mNum); printf("Human 拷贝构造\n"); } Human(Human && _h) { mNum = _h.mNum; // _h.mNum = nullptr; //必须将被偷者的指针置空,不然临时对象析构时会释放内存 printf("Human 移动构造\n"); } virtual ~Human() { printf("Human 析构\n"); if (mNum) delete mNum; } void show(){ if(mNum) printf("--- num:%d\n", *mNum); } private: int* mNum; }; Human GetHuman() { Human h1;//构造一个对象 return h1; //返回时,如果对象实现了移动构造(默认没实现),则会移动构造外部值 } //如果没有移动构造(默认实现拷贝构造 - 位拷贝),拷贝构造外部值 //位拷贝只是将里面的指针复制过来,还是指向同个内存,所以临时变量被析构后, //外部值的成员就指向了被释放过的内存地址,生命周期结束后将再次析构造成崩溃 Human GetHuman2() { return Human(); //直接构造给外部值,不会产生临时变量,也不会调用自定义拷贝构造或者移动构造,只会进行位拷贝,谨慎 } void testMoveConstruct() { Human h2 = GetHuman();//如果没有移动构造,将会调用拷贝构造,又涉及到深拷贝,但还是释放临时对象中产生的内存 h2.show(); //而移动构造直接使用临时对象中产生的内存,减少了一次new和delete的操作 system("pause"); } /* Human 构造 Human 移动构造 Human 析构 --- num:123 请按任意键继续. . . Human 析构 */
void testRValueRef1() { Human h2 = GetHuman2(); //因为直接构造给外部值作为临时变量,且这里是右值引用,所以生命周期随h2结束而结束 h2.show(); system("pause"); //h2 = GetHuman2(); //GetHuman2按位拷贝给h2,导致临时变量被析构后h2.num会指向被析构过的内存,h2生命周期结束再次delete num,崩 system("pause"); } /* Human 构造 --- num:123 请按任意键继续. . . 请按任意键继续. . . Human 析构 */
//形参是右值引用,所以必须为临时变量这种, void AcceptRValueRef(Human&& _h) { system("pause"); //1 Human h2 = std::move(_h); //这里将再次移动构造一个对象h2,待_h(临时对象)和h2对象的生命周期结束(这个方法结束)后都会析构 system("pause");//2 } void testRValueRef2() { AcceptRValueRef(GetHuman()); //GetHuman里会构造一个对象,然后移动构造一个临时对象作为形参传入 system("pause");//3 } /* Human 构造 Human 移动构造 Human 析构 请按任意键继续. . . //1 Human 移动构造 请按任意键继续. . . //2 Human 析构 Human 析构 请按任意键继续. . . //3 */
使用右值引用为临时对象 "续命"
利用移动构造和std::move实现高性能的置换swap
相关文章推荐
- 【C语言】递归实现栈的逆序及排序
- for循环 数组下标越界导致死循环
- c++11中的using关键字
- 编译原理(七) 算符优先分析法(构造算符优先关系表算法及C++实现)
- c++11中decltype的妙用
- bitset应用---产生1万个不重复的随机数
- c++11中的智能指针
- c++模板实现多参数任意传 - 类实现
- effective c++ 笔记之static_cast
- vs2008 dlib编译问题USER_ERROR__missing_dlib_all_source_cpp_file__OR__inconsistent_use_of_DEBUG_or_ENABLE
- 【C++】满二叉树与完全二叉树的区别及判断
- C++引用方式实现两个值的互换
- C++运算符重载
- C++抛出异常与传递参数的区别
- C++抛出异常与传递参数的区别
- C++【线程同步】-临界区同步
- c/c++进制转换
- C++的chrono、ratio和ctime等头文件
- leetcode Search a 2D Matrix
- C语言命名空间