类似于破窗理论,在前一周进行搬家之后休息了两天,感觉又将一部分的自己放到了舒适区,又在拷贝控制这章最后比较难的部分,感觉到自己的懈怠,在此提醒自己,希望可以对自己有一个警醒,不积跬步无以至千里~
13.49
String(String &&s):begin(std::move(s.begin)),end(std::move(s.end)){
begin = end = nullptr;
}
String& operator=(String &&s) {
if(this != &s){
this->begin = std::move(s.begin);
this->end = std::move(s.end);
s.begin = s.end = nullptr;
}
return *this;
}
StrVec(StrVec&& s):emlemnts(std::move(s.emlemnts)), first_free(std::move(s.first_free)), cap(std::move(s.cap)){
s.emlemnts = s.first_free = s.cap = nullptr;
};
StrVec& operator=(StrVec&&s){
if(this != &s){
free();
this->emlemnts = s.emlemnts;
this->first_free = s.first_free;
this->cap = s.cap;
s.emlemnts = s.first_free = s.cap = nullptr;
}
return *this;
};
Message(Message&& m):contents(std::move(m.contents)) {
folders = std::move(m.folders);
for(auto f: folders){
f->remMsg(&m);
f->addMsg(this);
}
m.folders.clear();
};
Message& operator=(Message&& m){
if(this != &m){
folders = std::move(m.folders);
for (auto f : folders) {
f->remMsg(&m);
f->addMsg(this);
}
m.folders.clear();
}
return *this;
};
13.50
增加移动拷贝构造函数后,当前所有操作都是使用移动拷贝构造函数
13.51
clone函数返回的是一个临时变量,在unique_ptr初始化时候使用了移动构造函数,将临时变量移动到了当前unique_ptr上所以说合法并且能正确的工作
13.52
hp通过赋值运算符拷贝了hp2的数据
hp通过移动赋值运算符获得了hp2的数据,之后的hp2将是未定义的,不能使用,在移动赋值运算符执行过程中,临时变量rhs由于HasPtr拥有移动拷贝构造函数,所以根据左值拷贝构造,右值移动拷贝构造的原则,rhs将通过移动拷贝构造函数获得hp2的值,并且交给了hp,
总的来说hp = std::move(hp2)一共执行了1次移动拷贝构造函数和一次移动赋值运算符
13.53
HasPtr& operator = (HasPtr& has){
if (this != &has) {
auto newps = new string(*has.ps);
delete ps;
ps = newps;
i = has.i;
}
return *this;
}
HasPtr& operator = (HasPtr&& has) {
//auto newps = new string(*has.ps);
if (this != &has) {
delete ps;
ps = std::move(has.ps);
i = std::move(has.i);
use_count = std::move(has.use_count);
}
return *this;
}
13.53
HasPtr& operator = (HasPtr& has){
if (this != &has) {
auto newps = new string(*has.ps);
delete ps;
ps = newps;
i = has.i;
}
return *this;
}
HasPtr& operator = (HasPtr&& has) {
//auto newps = new string(*has.ps);
if (this != &has) {
delete ps;
ps = std::move(has.ps);
i = std::move(has.i);
use_count = std::move(has.use_count);
}
return *this;
}
底层是由swap实现的,赋值运算符传入的是临时变量,在生成临时变量时会进行一次拷贝构造函数或移动拷贝构造函数操作,所以会有效率的影响,指定传入的左值引用和右值引用后,效率会提升
13.54
这个拷贝并交换运算符,半天没看懂,在查询网络大家的解题后,应该是指的最初的版本传入临时变量,并执行swap函数的赋值运算符版本,在同时存在移动赋值运算符和最初版本的情况下,赋值运算符的执行情况
HasPtr& operator = (HasPtr has) {
//auto newps = new string(*has.ps);
cout << "operator = (HasPtr has)" << endl;
if (this != &has) {
swap(*this, has);
}
return *this;
}
HasPtr& operator = (HasPtr&& has) {
cout << "operator = (HasPtr &&has)" << endl;
//auto newps = new string(*has.ps);
if (this != &has) {
delete ps;
ps = std::move(has.ps);
i = std::move(has.i);
use_count = std::move(has.use_count);
}
return *this;
}
结果如下
使用的拷贝并交换运算符