练习13.49
为你的StrVec、String和Message类添加一个移动构造函数和一个移动赋值运算符。
解答:
这里可以参考478页中HasPtr添加移动构造函数和移动赋值运算符的实现。
练习13.50
在你的String类的移动操作中添加打印语句,并重新运行13.6.1节(第473页)的练习13.48中的程序,它使用一个vector<String>,观察什么时候会避免拷贝。
解答:
#include <vector>
#include <iostream>
#include <string>
using namespace std;
class String{
public:
String() :str(string()){}
String(const char* cstr) :str(cstr){}
String(const String& ori) : str(ori.str){ cout << "copy constructor function" << endl; }
String(String&& ori) throw() : str(ori.str){ cout << "move copy constructor function" << endl; }
String &operator=(String &&rhs) throw(){
str = rhs.str;
return *this;
}
string str;
};
int main(){
vector<String> test;
test.push_back("haha0");
test.push_back("haha1");
test.push_back("haha2");
test.push_back("haha3");
test.push_back("haha4");
}
练习13.51
虽然unique_ptr不能拷贝,但我们在12.1.5节(第418页)中编写了一个clone函数,它以值方式返回一个unique_ptr。解释为什么函数是合法的,以及为什么它能正常工作。
解答:
这里对unique_ptr指针做的操作不是拷贝的操作,而是移动的操作,移动的操作对于unique_ptr来说是合法的,因为并没有拷贝当前指针,让多个指针对其产生共享。
练习13.52
详细解释第478也中的HasPtr对象的赋值发生了什么?特别是,一步一步描述hp,hp2以及HasPtr的赋值运算符中的参数rhs的值发生了什么变化。
解答:
在478页部分内容有比较详细的讲解。
对于HasPtr赋值中rhs发生了什么变化,因为执行的是交换操作,所以rhs的值会被其他值取代。
练习13.53:
略
练习13.54:
如果我们为HasPtr定义了移动赋值运算符,但未改变拷贝并交换运算符会发生什么?编写代码验证你的答案。
解答:
程序应该不会去调用移动赋值运算符,而会继续使用拷贝并交换运算符。
个人觉得的这里将“拷贝并交换运算符”换为“拷贝赋值运算符”可能更容易理解一些,因为在实现中,的确是先拷贝,然后再交换,来完成赋值操作的。