我在visual studio 11上尝试了一些新的C++ 11功能,从移动构造函数开始.我写了一个名为"MyClass"的简单类,其中包含一个移动构造函数:
class MyClass
{
public:
explicit MyClass( int aiCount )
: mpiSize( new int( aiCount ) ),
miSize2( aiCount)
{
}
MyClass( MyClass&& rcOther )
: mpiSize( rcOther.mpiSize )
, miSize( *rcOther.mpiSize )
{
rcOther.mpiSize = 0;
rcOther.miSize = 0;
}
~MyClass()
{
delete mpiSize;
}
private:
int *mpiSize;
int miSize2;
};
Run Code Online (Sandbox Code Playgroud)
我在这里有问题:
Set*_*gie 30
MSVC++在标准的最终版本发布之前实现了移动构造函数.在标准MSVC++的实现版本的基础上,生成默认移动构造函数的规则比标准的最终版本更严格.看到这里:为什么这段代码试图调用复制构造函数?(具体来说,这个答案及其评论)有关这方面的更多信息.由于它们有其他优先级,因此一些未知的愚蠢原因在Visual Studio 11中没有也不会修复.
不,您需要调用std::move成员rcOther,并使用垂死对象(您错误命名miSize)中的相应成员初始化成员:
MyClass( MyClass&& rcOther )
: mpiSize( std::move(rcOther.mpiSize) )
, miSize2( std::move(rcOther.miSize2) )
{
rcOther.mpiSize = 0;
}
Run Code Online (Sandbox Code Playgroud)
对于像int和的内置类型而言int*,它没有什么区别,但它肯定会对用户定义的类型产生影响.
std::move只返回被转换为T&&一个rvalue-reference的参数,以便T(T&&)为每个子对象调用正确的构造函数(移动构造函数).如果你不使用std::move垂死对象的成员,它们将被视为T&,并且T(T&)将调用子对象()的复制构造函数而不是移动构造函数.这是非常糟糕的,并且几乎打破了编写移动构造函数的整个目的.
3.你正在做一些不必要的事情,比如将整数设置为0.你只需要将指针设置为0,这样delete它就不会删除你创建的新对象的资源.
此外,如果这不是一个教学练习,您可能需要考虑使用std::unique_ptr而不是管理自己对象的生命周期.这样你甚至不必为你的类编写析构函数.请注意,如果这样做,则必须使用std::move从移动构造函数中的垂死成员初始化成员.
Kon*_*lph 13
如果不这样做,编译器会生成一个移动构造函数 - 经过时尚之后.但是,编译器无法猜测您的动机,因此它不知道您的类中的指针是什么.特别是,它不知道指针赋予内存的所有权并且需要被淘汰.
移动构造函数是正确的1但是其他类没有,你违反了三条规则:你的类需要一个合适的拷贝构造函数和拷贝赋值运算符.
编写移动构造函数的更好方法如下:
MyClass(MyClass&& rcOther)
: mpiSize(std::move(rcOther.mpiSize))
, miSize2(std::move(rcOther.miSize2))
{
rcOther.mpiSize = 0;
}
Run Code Online (Sandbox Code Playgroud)
两条评论:
rcOther.mpiSize?虽然这没有错,但它也毫无意义并且具有误导性.但更好的方法是依靠已有的设施.在这种情况下,您需要为内存所有权建模.一个裸指针做得不好,你应该使用一个std::unique_ptr.这样,您不需要实现析构函数或移动构造函数,因为自动生成的方法是正确的.
1 警告:请参阅塞思的回答,以便提及更好的解释std::move(但在这种特殊情况下,这是一个无操作).
从 C++14 开始,您可以利用std::exchange()方便的函数模板来定义移动构造函数。这可能会导致更简洁的移动构造函数定义:
MyClass(MyClass&& other) noexcept:
mpiSize(std::exchange(other.mpiSize, nullptr)),
miSize2(std::exchange(other.miSize2, 0))
{}
Run Code Online (Sandbox Code Playgroud)
std::exchange(other.mpiSize, nullptr)other.mpiSize替换with的值,但返回替换之前的nullptr值。other.mpiSize
| 归档时间: |
|
| 查看次数: |
14473 次 |
| 最近记录: |