在主函数中首先构建了s1对象 第二步调用fun函数,fun函数中创建了s2对象,拿yhping初始化s2对象,然后return s2的时候,正常情况下会有一个无名对象到主函数的栈帧,然后析构s2对象,当fun将s2对象中的yhpiing赋值给s1的时候,无名对象被释放 正常逻辑是这样的
但是当给到移动构造函数的时候 为啥return s2的时候 就会调用移动构造函数了 还有就是是如何调用这个函数的呢
在没有编译器优化的情况下,如果一个函数按值返回并且返回值类型定义了移动构造函数,那么编译器会调用移动构造函数来构造函数的返回值临时对象。如果返回值类型没有定义移动构造函数,那么编译器会调用拷贝构造函数来构造返回值临时对象。
不过现在主流C++编译器都默认打开了返回值优化(RVO),所以前面两种情况,调用移动构造函数或拷贝构造函数直接被优化掉了。
当然编译的时候你可以关闭RVO优化选项(比如g++ -fno-elide-constructors
),就可以看到移动构造函数或拷贝构造函数被调用的情况。
注意移动构造函数和移动赋值运算符里,是直接拷贝指针的,而不是字符串拷贝,所以效率高。并且右值引用对象里的指针被置空,所以当右值引用对象析构时,不会释放原来的字符串。
参考
https://en.cppreference.com/w/cpp/language/move_constructor
这个移动拷贝和移动赋值函数的作用不就是减少对堆空间的申请和释放,那么调用的时候 应该逃不过一点 就是在fun函数中创建的s2对象 在fun函数结束之后 s2所new的堆空间 应该是被释放了 为什么到后面还可以让s1或者是无名对象来指向s2对象new出来的堆空间
移动构造函数调用了两次?
在没有编译器优化的情况下,如果一个函数按值返回并且返回值类型定义了移动构造函数,那么编译器会调用移动构造函数来构造函数的返回值临时对象。如果返回值类型没有定义移动构造函数,那么编译器会调用拷贝构造函数来构造返回值临时对象。
不过现在主流C++编译器都默认打开了返回值优化(RVO),所以前面两种情况,调用移动构造函数或拷贝构造函数直接被优化掉了。
当然编译的时候你可以关闭RVO优化选项(比如g++ -fno-elide-constructors
),就可以看到移动构造函数或拷贝构造函数被调用的情况。
注意移动构造函数和移动赋值运算符里,是直接拷贝指针的,而不是字符串拷贝,所以效率高。并且右值引用对象里的指针被置空,所以当右值引用对象析构时,不会释放原来的字符串。
参考
https://en.cppreference.com/w/cpp/language/move_constructor