13.45
平时引用是左值引用,当时用&&的时候就是右值引用比如
左值引用:
int a = 2;
int &p = a;
右值引用:
int &&p = 3;
int &&q = p;
左值持久,右值短暂,左值具有持久的状态,右值要么是字面值常量,要么是在表达式求值的过程中创建的临时对象(没有其他用户进行绑定且要被销毁):使用右值引用的代码可以自由的接管所引用的对象的资源
13.46
f()返回值类型是int,属于使用f()后才有的临时变量,使用&&
&
&
&&
13.47
String::String(const String&s){
std::cout<<"拷贝构造函数"<<std::endl;
auto newStr = alloc_n_copy(s.elements,s.first_free);
elements = newStr.first;
first_free = newStr.second;
}
String& String::operator=(const String&a){
std::cout<<"拷贝赋值运算符"<<std::endl;
auto newc = alloc_n_copy(a.elements,a.first_free);
free();
elements = newc.first;
first_free = newc.second;
return *this;
}
13.48
不知道为啥申请不到空间,我再看看
#include <iostream>
#include"String.h"
#include<vector>
using namespace std;
int main()
{
std::vector<String> vec;
String s1("xxx");
String s2 = s1;
vec.push_back(s1);
vec.push_back(s2);
return 0;
}
13.49
Message类
//从本message移动Folder指针
void Message::move_Folders(Message *m){
folders = std::move(m->folders);
for(auto v:folders){
v->remMsg(m);
v->addMsg(this);
}
m->folders.clear();
}
//移动构造函数
Message::(Message &&m){
contents = m.contents;
move_Folders(&m);
}
//移动赋值运算符
Message& Message::operator=(Message &&rhs){
if(this!=&rhs){
remove_from_Folders();
contents = std::move(rhs.contents);
move_Folders(&rhs);
}
return *this;
}
StrVec类
//移动构造函数
StrVec::StrVec(StrVec &&s) noexcept:elements(s.elements),first_free(s.first_free),cap(s.cap){
//另s进入这样的状态-----对其运行析构函数是安全的
s.elements = s.first_free = s.cap = nullptr;
}
//移动赋值运算符
StrVec &StrVec::operator=(StrVec &&rhs) noexcept{
//首先检测自身赋值
if(this != &rhs){
free(); //释放已有元素
elements = rhs.elements; //从rhs接管资源
first_free = rhs.first_free;
cap = rhs.cap;
//将rhs置于可析构的状态
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}
String类
//移动构造函数
String::String(String &&s) noexcept{
std::cout<<"移动构造函数"<<std::endl;
elements = s.elements;
first_free = s.first_free;
s.elements = s.first_free = nullptr;
}
//移动赋值运算符
String &String::operator=(String &&rhs) noexcept{
std::cout<<"移动赋值运算符"<<std::endl;
if(this!=&rhs){
free();
elements = rhs.elements;
first_free = rhs.first_free;
rhs.elements = rhs.first_free = nullptr;
}
return *this;
}
13.50
参考cpp答案
#include <iostream>
#include"String.h"
#include<vector>
using namespace std;
String R(){
std::vector<String> vec;
String s1("s");//默认构造函数
vec.push_back(s1);//拷贝构造函数
return s1;//临时量,移动构造函数
}
int main()
{
String s=R();//移动构造函数
return 0;
}
13.51
这里使用了移动构造函数,因为new int(p)是一个产生临时变量的表达式,所以它是一个右值,所以这里可以使用移动构造函数
13.52
hp2是左值,实用拷贝构造函数
std::move(hp2);
就是使用移动操作啦std::move(hp2);
是右值,可以使用移动构造函数
13.53
缺少移动操作,书上版本
//移动构造函数
HasPtr(HasPtr &&p) noexcept{
ps = p.ps;
i = p.i;
p.ps = 0;
}
//赋值运算符既算是移动赋值运算符也算是拷贝赋值运算符
HasPtr& operator=(HasPtr rhs){
swap(*this,rhs);
return *this;
}
13.54
C:\wook_tool\MyCppSpace\primer_13_3\main.cpp|12|error: ambiguous overload for 'operator=' (operand types are 'HasPtr' and 'std::remove_reference<HasPtr&>::type {aka HasPtr}')|
13.55
void StrVec::push_back(std::string &&s){
chk_n_alloc(); //确保有空间容纳新的元素
alloc.construct(first_free++,std::move(s)); //在first_free指向的元素中构造s的副本
}
13.56
ret是左值对象,是一直调用当前的sort,递归
13.57
Foo(*this)只会产生临时对象,就会调用&&版本的sort
13.58
#include <vector>
#include <iostream>
#include <algorithm>
using std::vector; using std::sort;
class Foo
{
public:
Foo sorted() && ;
Foo sorted() const &;
private:
vector<int> data;
};
Foo Foo::sorted() && {
sort(data.begin(), data.end());
std::cout << "&&" << std::endl; // debug
return *this;
}
Foo Foo::sorted() const &
{
// Foo ret(*this);
// sort(ret.data.begin(), ret.data.end());
// return ret;
std::cout << "const &" << std::endl; // debug
// Foo ret(*this);
// ret.sorted(); // Exercise 13.56
// return ret;
return Foo(*this).sorted(); // Exercise 13.57
}
int main()
{
Foo().sorted(); // call "&&"
Foo f;
f.sorted(); // call "const &"
}
网友评论