提问者:小点点

如何确保在使用std::move时永远不会调用复制构造函数


请参见下面的代码。我注释移动构造函数,而不是编译错误,复制构造函数现在被调用!尽管我使用的是

如果我使用,如何确保我巨大的对象从不调用复制构造函数(例如,我忘记添加移动构造函数)?

class MyHugeObject
{
public:
    MyHugeObject()
    {
    }
    MyHugeObject(const MyHugeObject& m)
    {
        std::cout << "copy huge object\n";
    }
    // MyHugeObject(MyHugeObject&& m)
    // {
    //     std::cout << "move huge object\n";
    // }
};

MyHugeObject func()
{
    MyHugeObject m1;
    MyHugeObject&& m2 = std::move(m1);
    return std::move(m2);
}

int main()
{
    auto m = func();
    return 0;
}

输出:

copy huge object

共3个答案

匿名用户

如果您类型的复制构造特别昂贵或有问题,但又不是您想要完全禁止的事情,则可以将复制构造函数标记为。如果没有显式请求,显式复制构造函数将不允许复制(例如,您不能使用它按值自动传递参数),但仍可用于显式复制构造。同时,隐式移动结构仍然可以被允许。

匿名用户

当您使用rvalue而不是lvalue时,它将允许您在没有复制构造函数的情况下移动。在您的示例中,应该使用MyHugeObject(MyHugeObject&Amp&Amp),因为作为参数,它将得到一个rvalue。

匿名用户

正如注释中所指出的,您可以删除copy构造函数和move运算符,但这将意味着该对象是绝对不可复制的,即使在某些情况下您希望它是可复制的。

相反,您可以创建一个unittest来检查是否确实在使用问题中的代码时执行了移动(但注意,这将需要更多的工作):

class MyHugeObject
{
private:
    some_resource res;

...
};

...

// Test

MyHugeObject m1;
// Record here the resource inside m1
MyHugeObject&& m2 = std::move(m1);
// Check here the resource has been moved to m2
// Also, check that m1 is in a valid post-move state 
//  (e.g., if the resource is a pointer, that it is null)