相比于 java ,c++ 因为要自己管理内存,管理类使用过程中的内存,又因为效率的考虑,所以产生了各种用于类的初始化和赋值的函数,下面就各种函数被调用到的场景做了个测试。
#include <iostream>
using namespace std;
#include <utility>
class A{
public:
A(){cout << "construct" << endl;};
A(const A &a){cout << "copy construct" << endl;};
A &operator=(A &a){cout << "copy operate= " << endl; return *this;}
A(A &&a) noexcept {cout << "move copy construct" << endl;};
A &operator=(A &&a) noexcept {cout << "move copy operate=" << endl; return *this;}
static A factory(){return A();};
static void fun(A a){};
};
int main() {
A a; //construct
A a1 = A(); //construct
A a2 = A::factory(); //construct NRV优化
A a3(A::factory()); //construct NRV优化
A a4( ( A() ) ); //construct
A a5( A() ); //A(void)函数声明
A a6(); //返回A的a6(void)函数声明
A::fun(a); //copy construct
A a7 = a; //copy construct
a1 = a; //copy operate=
a1 = A(); //construct move copy operate=
A a8(std::move( A() )); //construct move copy operate=
return 0;
}
**总结:当一个类定义了自己的拷贝构造函数,拷贝赋值运算符或者析构函数,编译器就不会
为它合成移动构造函数和移动赋值运算符了。我猜测这种设定是因为,既然你需要自己
来管理这个类里面的内存了,比如里面有个指针,你也许会在析构函数里释放它,
那么,编译器合成的移动构造函数
和移动赋值运算符就不能满足需求,因为它并不会将指针置为 nullptr 那么当这个源
对象析构的时候,移动的东西就没了,问题也就出现了。
当移动和拷贝都存在时,右值移动,左值拷贝,当移动不存在,右值也拷贝**