1.拷贝构造函数和移动构造函数
总的来说,都是用一个已有的对象去创建构造一个新的对象。
当对象中含有指针或类作为数据成员的,对于已有的对象在构造出新的对象后,仍需要对该已有对象进行引用或利用的,需要我们自己定义拷贝构造函数(进行深拷贝)。
而对于已有的对象在构造出新的对象后,将不再对该已有对象进行引用或利用的,需要我们自己定义移动构造函数(进行浅拷贝)。
拷贝构造函数和移动构造函数调用规则可以按下图1-1进行:
图1-1 拷贝构造函数和移动构造函数的简单调用规则图
2.拷贝赋值函数和移动赋值函数
对于拷贝赋值和移动赋值,则都是用一个已有对象将其值赋值给另一个已有对象。
其调用赋值函数类型的规则与拷贝构造函数和移动构造函数调用规则相似,都是根据对象是否继续进行利用选择,调用规则可以按下图1-2进行:
图1-2 拷贝赋值和移动赋值的简单调用规则图
代码测试实验代码:
//拷贝构造函数 vector (const vector &rhs ):theSize{rhs.theSize}, theCapacity{ rhs.theCapacity }, objects{ nullptr } { objects = new Object[theCapacity]; for (int i = 0; i < theSize; ++i) objects[i] = rhs.objects[i]; std::cout << "拷贝构造" << std::endl; } //拷贝赋值函数 vector & operator =(const vector &rhs) { vector copy = rhs; std::swap(*this, copy); /*利用移动交换 void swap(vector<object> &x,vector <object> &y) { vector<object> temp = std:: move( x ); x = std::move( y ); y = std::move( temp ); } 若是利用赋值交换,则会进入死循环 void swap((vector<object> &x,vector <object> &y) { vector<object> temp = x ; //这里会重新调用赋值函数,陷入死循环 x = y ; y = temp ; } */ std::cout << "拷贝赋值" << std::endl; return *this; } //移动构造函数 vector (vector && rhs):theSize{rhs.theSize}, theCapacity{ rhs.theCapacity }, objects{ rhs.objects }//objects 这里与拷贝构造函数不同了,拷贝的是null { rhs.objects = nullptr; rhs.theSize = 0; rhs.theCapacity = 0; std::cout << "移动构造" << std::endl; } //移动赋值函数 vector &operator =(vector && rhs) { std::swap(theSize, rhs.theSize); std::swap(theCapacity, rhs.theCapacity); std::swap(objects, rhs.objects); /*利用赋值交换 void swap((vector<object> &x,vector <object> &y) { vector<object> temp = x ; x = y ; y = temp ; } 若是利用移动交换,则会进入死循环 void swap(vector<object> &x,vector <object> &y) { vector<object> temp = std:: move( x ); //这里会重新调用移动函数,陷入死循环 x = std::move( y ); y = std::move( temp ); } */ std::cout << "移动赋值" << std::endl; return *this; }