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

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(默认,啥都没调过),是不是应该设置下编译命令行什么的。好吧这个我可以自己去谷歌,实在是因为今天看的头有点太晕了··
先谢过各位大佬了,小弟今天实在是被右值引用给绕晕了··如果有什么低级问题还忘轻喷··
...全文
416 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执行停在该断点处的时候。
内容概要:本文详细介绍了C++中的移动构造函数及其相关概念,重点阐述了移动语义在资源管理中的应用与优势。通过一个完整的代码示例,展示了类的默认构造函数、复制构造函数移动构造函数、复制赋值运算移动赋值运算的具体实现方式。移动构造函数利用右值引用将资源所有权从源对象高效转移到新对象,避免了深拷贝带来的性能损耗,尤其适用于处理大对象或频繁进行临时对象操作的场景。文章还解释了std::move的作用机制,即强制将左值转换为右值引用,从而触发移动操作而非复制操作。; 适合人群:具备一定C++基础,理解类、构造函数、析构函数和动态内存管理的初级到中级开发者;适合正在学习现代C++特性(如右值引用移动语义)的学生或研发人员; 使用场景及目标:①深入理解C++11引入的移动语义和右值引用机制;②掌握如何手动实现高效的资源管理类,避免不必要的内存复制;③提升对STL容器中对象移动行为的理解与应用能力; 阅读建议:此资源侧重于移动语义的核心原理与编码实践,建议读者结合代码逐行理解各成员函数的行为差异,特别是移动后的对象状态变化,并通过调试运行观察构造、析构及移动调用时机,以强化对资源安全转移的认知。

33,318

社区成员

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

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