编译器在VC12中生成移动构造函数行为(VS2013)

时间:2015-07-09 16:41:05

标签: c++ c++11 visual-studio-2013 move

我试图测试编译器为具有数据成员的类生成的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)的已知限制吗?

1 个答案:

答案 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,也会调用复制构造函数。

根据标准,编译器不需要生成默认移动构造函数的原因有很多,但是您的类似乎没有违反其中任何一个。