右值引用,移动构造函数 移动赋值符相关。

ftdch 2018-03-15 11:27:17
最近看C++ PRIMER第五版···对于里面的这几个概念有点混淆,网上看的不明不白的,决定还是发帖问下,首先上代码:

"cc.h":
class CC
{
friend void swap(CC& lhs, CC& rhs);
public:
CC(std::string& s = std::string()) :ps(new std::string(s)),val(0) {
}
CC(const CC& c) : ps(new std::string(*c.ps)),val(c.val) {
}
CC(CC&& rc) noexcept :val(rc.val),ps(rc.ps) {
rc.ps = nullptr;
}
CC& operator= (const CC& rhs) {
CC tmp(rhs);
swap(*this, tmp);
return *this;
}
CC& operator=(CC&& rhs) {
swap(*this, rhs);
return *this;
}
//CC& operator= (CC rhs){
// swap(*this, rhs);
// return *this;
//}
~CC() {
delete ps;
ps = nullptr;
};

private:
std::string* ps;
int val;
};

inline void swap(CC& lhs, CC& rhs) {
std::swap(lhs.ps, rhs.ps);
std::swap(lhs.val, rhs.val);
}
"main.cpp":
CC getRF() {
return CC("from getRF");
}
void testRref() {
CC c1;
CC&& c2 = std::move(c1);
CC c3 = c2;
c3 = getRF();
CC c4 = std::move(c2);
CC c5 = "C++";
CC c6 = getRF();
}


这上面代码基本是我参考书上写出来的。然后下面是问题:
问题1:我在网上看移动构造函数的时候,发现一篇微软官方文档。https://msdn.microsoft.com/zh-cn/library/dd293665.aspx。在里面的移动构造函数实现细节稍微,有点不同,具体如下:

CC(CC&& rc) :ps(nullptr),val(0) {
ps = rc.ps;
val = rc.val;
rc.ps = nullptr;
rc.val = 0;
}

这里是在初始化列表先将原来的置空,然后再进行拷贝操作,这样和我原代码中直接进行拷贝操作有区别吗?
问题2:跑了以后发现c3 = c2调用的是拷贝构造函数,所以说我是不是可以这么理解,在C++里面,所有带名字的(变量),不管他的类型是啥,就算他类型是右值引用,都是左值,只有没有名字的值、函数传参或者返回一个对象以及std::move()产生的东西才是右值。
问题3:关于移动赋值符的重载。到底应该用CC(CC&& cc)还是CC(CC rhs)呢?看书上2个都好像用过。但是为啥我用CC(CC rhs)的时候,提醒我c3 = getRF()具有二义性,用右值引用版本的赋值符重载就可以运行。
问题4:还有顺便提一句C5和C6都调用的是默认构造函数,是不是编译器给我优化了= =我的代码运行环境是VS2017(默认,啥都没调过),是不是应该设置下编译命令行什么的。好吧这个我可以自己去谷歌,实在是因为今天看的头有点太晕了··
先谢过各位大佬了,小弟今天实在是被右值引用给绕晕了··如果有什么低级问题还忘轻喷··
...全文
397 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2018-03-16
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! 不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他!单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。 VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧