为什么我们需要在C ++中使用移动构造函数/赋值运算符:
Foo(const Foo& x, bool copy = false) {
if (copy) {
// copy
}
else {
// move
}
}
或者我错过了什么?
答案 0 :(得分:1)
C ++中的类可以代表任何东西。文件,线程,字符串,3d对象 - 所有这些都可以表示为某个类的实例。这些对象可能包含大量内部数据。请考虑以下示例:
class Image
{
protected:
Ubyte* _data;
Size _size;
PixelFormat _pixel_format;
public:
Image()
: _data(nullptr)
, _size(0,0)
, _pixel_format(PixelFormat::Unknown)
{
}
Image(Image&& source)
: _data(nullptr)
, _size(0,0)
, _pixel_format(PixelFormat::Unknown)
{
this->Swap(source);
}
Image(const Image& origin)
: _data(nullptr)
, _size(0,0)
, _pixel_format(PixelFormat::Unknown)
{
this->InitWithDeepCopyOf(origin);
}
void Swap(Image& other)
{
std::swap(this->_data, other._data);
std::swap(this->_size, other._size);
std::swap(this->_pixel_format, other._pixel_format);
}
};
InitWithDeepCopyOf(const Image&amp; img)使用存储在img中的数据初始化图像,但它首先完全复制该数据(考虑使用全高清分辨率的32bpp图像 - InitWithDeepCopyOf()将复制8.3MB数据!)。< / p>
在我们的计划中,我们有另一个班级:
class ImageHolder
{
protected:
Image _image; //stores image by value
public:
ImageHolder()
{
}
ImageHolder(ImageHolder&& source)
: _image(std::move(source._image))
{
}
ImageHolder(const ImageHolder& origin)
: _image(source._image)
{
}
};
在ImageHolder
的移动ctor中,我们简单地移动了构造_image
成员,因此它将采用Image
和3个交换的默认初始化。复制构造函数需要复制构造_image
,因此所有数据都将被复制。
让我们考虑使用bool
标志的解决方案。它有两个问题:
1)我们不能正确地做到这一点。
ImageHolder(const ImageHolder& origin, bool copy = true)
: _image(source._image)
{
if(copy)
//...
else
//...
}
如果将origin
声明为const ImageHolder&amp ;,我们就无法移动它,因为移动需要修改源对象 - 我们无法修改const对象。
如果origin
被声明为非const ImageHolder&amp;,我们将无法执行此操作:
ImageHolder new_holder(ImageHolder(image)); //parameter is a const reference
2)在构造者的身体中,成员已经构建。
当我们达到此代码时:
if(copy)
//...
else
//...
_image
已经构建(更确切地说:复制构造),这意味着您已经复制了所有数据(因此移动任何东西都没有意义)。
所以,是的,这完全取决于性能。如果你认为,你可以将CPU时间浪费在不必要的数百兆字节数据上......毕竟,这只是关于性能的。
答案 1 :(得分:1)
为您隐式编写移动构造函数(除非您阻止它)。
在某些上下文中会自动为您调用移动构造函数,即使您在它们存在之前编写了代码。
只有移动构造函数可以存在移动类型,并且它们在编译时阻止复制操作并带有错误。
将某些内容标记为&#39;请从此处移除&#39;不需要第二个参数,完成转发工作。完美转发也适用于右值。 (完美的转发是不完美的,顺便说一句)
移动作业不会很好地适应您的模式。
rvalue ref在move / assign之外的上下文中很有用。
老实说,将C ++ 11 move和rvalue refs与你的提议进行比较就好像问为什么Telsa比带有破碎轮子的三轮车更好。破碎的三轮车更便宜,我会批准它。