繁体   English   中英

根据移动赋值运算符移动构造函数

[英]Move constructor in terms of move assignment operator

在我们项目的代码库中,我发现了这样的事情:

struct MeshData {
    MeshData() {}
    MeshData(MeshData&& obj) { *this = std::move(obj); }
    MeshData& operator=(MeshData&& obj) {
        if (this != &obj) {
            indexes = std::move(obj.indexes);
        }
        return *this;
    }
    std::vector<int> indexes;
};

在移动分配方面实现移动构造对我来说似乎是一个聪明的想法,减少了代码重复,但在查找信息之后,我没有找到任何关于此的具体建议。

我的问题是:这是反模式还是有任何不应该做的情况?

如果您的类型的数据成员没有默认构造函数,则无法执行此操作,如果它们具有昂贵的默认构造函数,则不应执行此操作:

struct NoDefaultCtor {
    NoDefaultCtor() = delete;
    NoDefaultCtor(int){}
};

struct Foo {
    Foo(Foo&& obj) { *this = std::move(obj); }
    Foo& operator=(Foo&& obj) {
        if (this != &obj) {
            thing = std::move(obj.thing);
        }
        return *this;
    }
    NoDefaultCtor thing;
};

给出了这个错误:

<source>: In constructor 'Foo::Foo(Foo&&)':
<source>:10:20: error: use of deleted function 'NoDefaultCtor::NoDefaultCtor()'
     Foo(Foo&& obj) { *this = std::move(obj); }
                    ^
<source>:5:5: note: declared here
     NoDefaultCtor() = delete;

这是因为必须在输入构造函数体之前构造所有数据成员。

但是,最好的建议是遵循零规则,并避免编写这些特殊成员。

当移动构造函数和移动成员变量的运算符可能产生不同的结果时,这种方法的一个缺陷就会表现出来。 例如,如果indexes是使用自定义分配器的vector并且std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value evaluation to true则会发生这种情况。 在这种情况下,专用移动构造函数将移动分配器和数据而不抛出异常,而调用移动分配将导致分配新存储并且所有项目移动构造导致相当大的开销并防止移动构造函数不被抛出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM