一个关于C++移动构造函数问题
C++primer书上的例子 StrVec 是一个仿vector<string>的类
其中移动赋值运算符为:
StrVec &StrVec::operator=(StrVec &&rhs) noexcept
{
if(this!=&rhs){ //检测是否是字符值
free();
elements = rhs.elements; //elements是一个指向第一个元素的指针
first_free = rhs.first_free; //first_free是指向第一个未使用的空间
cap = rhs.cap; //cap是尾后指针
rhs.elements = rhs.first_free = rhs.cap = nullptr; //使其实可析构的
}
return *this;
}
在上面代码中,传入的实参是一个rvalue,后面的交换资源管理 也是移动也就是说
elements = rhs.elements; 指的是移动,elements窃取了rhs.elements的资源。
下面是另一个例子 Message的一个类
Message &Message::operator=(Message &&rhs)
{
if(this!=&rhs){ //检查自赋值
remove_from_Folders();
contents = std::move(rhs.contents); //移动赋值操作 contents是一个string
move_Folders(&rhs); //重置Floders指向本Message
}
return *this;
}
我的问题是 :在Message中rhs也是一个rvalue,然后下面的接管资源的时候为什么要是:contents = std::move(rhs.contents);
而不直接是contents = rhs.contents; 。还是说加上std::move是为了显示的说明要调用移动赋值运算符?还是说StrVec中
elements = rhs.elements;只是拷贝了指针???
贴上C++Primer上的这两个类的完整成员:
class StrVec{
public:
StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){}//默认构造函数
StrVec(initializer_list<string>);
StrVec(const StrVec &); //拷贝构造函数
StrVec &operator=(const StrVec &); //拷贝赋值运算符
StrVec(StrVec &&); //移动构造函数
StrVec &operator=(StrVec &&); //移动赋值运算符
~StrVec(); //析构函数
void push_back(const string &); //拷贝元素
void push_back(string &&); //移动元素
size_t size() const {return first_free-elements;}
size_t capacity() const {return cap-elements;}
string *begin()const{return elements;}
string *end()const{return first_free;}
StrVec &reserve(size_t n); //分配大小为n空间
StrVec &resize(size_t n); //重置空间大小为n
private:
string *elements; //指向起始元素
string *first_free; //第一个非实际元素
string *cap; //指向尾后位置的指针
//static allocator<string> alloc; //分配元素
void chk_n_alloc(){if(size()==capacity()) reallocate();} //检查空间是否够大
pair<string*,string*> alloc_n_copy(const string*,const string*);
void free(); //销毁元素并释放内存
void reallocate(); //获得更多内存并拷贝已有元素
void reallocate();
};
class Message{
public:
friend class Floder;
friend void swap(Message &lhs,Message &rhs);
explicit Message(const string &str = ""):contents(str) { }
//拷贝控制成员
Message(const Message &);
Message &operator=(const Message &);
Message(Message &&); //移动构造函数
Message &operator=(Message &&); //移动赋值运算符
~Message();
//从给定Folder添加/删除本Message
void save(Folder&);
void remove(Folder&);
private:
string contents;
set<Folder*> folders;
//拷贝构造函数,拷贝赋值运算符合析构函数所使用的工具函数
void add_to_Folders(const Message &);//将本message添加到指向参数的Folder中
void remove_from_Folders();//从folder中每个Folder中删除本Message
void addFldr(Folder* f){folders.insert(f);}
void remFldr(Folder* f){folders.erase(f);}
void move_Folders(Message *m);
};