我试图测试编译器为具有数据成员的类生成的Move Constructor的行为" std :: string"和" std :: shared_ptr"。
class Record
{
public:
Record():mData("defRec"), mDataPtr(new std::string("defRec"))
{}
Record(const std::string &str): mData(str), mDataPtr(new std::string(str))
{}
private:
std::string mData;
std::shared_ptr<std::string> mDataPtr;
};
任何D&amp; tor,移动和复制操作都被故意省略,以允许编译器生成Move操作。特别选择了类数据成员,因为与Record类不同,它们都定义了D&lt; tor,move和copy操作。
在以下代码之后,
Record rec1(std::string("Record1"));
Record rec2(std::move(rec1));
检查对象rec1(通过调试器或通过定义访问方法),mData仍包含&#34; Record1&#34;并且mDataPtr仍然保存字符串指针。
但是,如果我提供我自己的Move Constructor,如下所示
Record(Record&& rhs) : mData(std::move(rhs.mData)), mDataPtr(std::move(rhs.mDataPtr))
{}
然后在以下代码之后
Record rec1(std::string("Record1"));
Record rec2(std::move(rec1));
在检查对象rec1时,mData和mDataPtr都变为空对象。
我不明白为什么编译器会为&#34;类记录&#34;生成移动构造函数。给我的版本的移动构造函数给出了不同的结果&#34; class Record&#34;我只是确保调用数据成员的移动C。我期望编译器生成移动构造函数的行为相同吗?
虽然从对象移动应该处于有效状态,但数据成员&#39;移动构造函数(两次都没有定义)给出不同的结果。
这是VC12(VS2013)的已知限制吗?
答案 0 :(得分:4)
是的,这是该编译器的已知限制。来自Can a move constructor be implicit?的问题EDIT EDIT
告诉我们:
编辑编辑我踩了Stephan T Lavavej并问他为什么VC 2012没有 似乎遵循12.8关于隐含行动的草案 构造函数生成。他很友好地解释道:它还有一个尚未实现的功能&#34;而不是一个bug。 VC目前实现了我所称的rvalue references v2.0,其中 移动ctors / assign永远不会隐式生成,永远不会影响 隐含生成复制ctors / assign。 C ++ 11指定rvalue 引用v3.0,这是你正在查看的规则。
简而言之,编译器永远不会生成移动构造函数,即使存在显式std::move
,也会调用复制构造函数。
根据标准,编译器不需要生成默认移动构造函数的原因有很多,但是您的类似乎没有违反其中任何一个。