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

Compiler generated move constructor behavior in VC12 (VS2013)

本文关键字:移动 构造函数 VC12 VS2013 编译器      更新时间:2023-10-16

我试图测试编译器生成的移动构造函数的行为为一个类的数据成员为"std::string"answers"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'tor、move和copy操作都被故意省略,以允许编译器生成move操作。类数据成员被特别选择,因为与Record类不同,它们都定义了D'tor、移动和复制操作。

在以下代码之后,

Record rec1(std::string("Record1"));
Record rec2(std::move(rec1));

检查对象rec1(通过调试器或通过定义访问方法),mData仍然包含"Record1"和mDataPtr仍然持有字符串指针。

但是,如果我提供自己的Move构造函数,如下所示

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都变为空对象。

我不明白为什么编译器生成的移动构造函数为"类记录"给出了不同的结果,我的版本移动构造函数为"类记录",我只是确保移动C'tor的数据成员被调用。我期望相同的行为编译器生成移动构造函数?

虽然被移动的from对象应该处于有效状态,但数据成员的move构造函数(在这两种情况下都没有定义)给出了不同的结果。

这是VC12 (VS2013)的已知限制吗?

是的,这是该编译器的已知限制。move构造函数可以是隐式的吗?问题的EDIT EDIT告诉我们:

我联系了Stephan T Lavavej,问他为什么VC 2012没有似乎遵循草案12.8关于含蓄行动的规定构造函数生成。他好心地解释了:

这更像是一个"尚未实现的功能",而不是一个bug。VC目前实现了我所说的右值引用v2.0,其中移动因子/赋值永远不会隐式生成,也不会影响隐式生成复制因子/赋值。c++ 11指定了右值参考v3.0,这是您正在查看的规则。

简而言之,编译器永远不会生成move构造函数,即使在显式std::move存在的情况下,也会调用copy构造函数。

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