通过移动赋值

时间:2018-02-23 15:48:08

标签: c++ c++11

我们说我有以下最小的示例类:

#include <iostream>

class Foo {
public:
    Foo() = default;

    Foo(const Foo&) = default;
    Foo(Foo&&) noexcept = default;

    Foo& operator=(const Foo& rhs) {
        std::cout << "copy\n";

        return *this;
    }

    Foo& operator=(Foo&& rhs) noexcept {
        std::cout << "move\n";

        return *this;
    }

    Foo operator+(const Foo& rhs) const {
        Foo x; // with some calculation

        return x;
    }
};

int main() {
    Foo a, b, c;

    a = b + c;
}

按预期打印move。现在根据Effective C ++ Item 3,我应该从const Foo返回operator+以避免构造像a + b = c,即:

// To avoid a + b = c
const Foo operator+(const Foo& rhs) const {}

不幸的是,这突然开始调用复制赋值而不是移动赋值运算符。 [我在Ubuntu上使用gcc 4.8.4,但它可能与编译器无关]

如何确保a + b = c无法编译,同时为a = b + c调用移动分配?或者随着移动语义的引入,有没有办法在同一时间实现它们两者?

1 个答案:

答案 0 :(得分:2)

我最终使用了Caninonos在评论中指出的左值参考限定符,以及现在删除的答案中的max66(但是10k用户可以看到它)。

Foo& operator=(const Foo& rhs) & {}
Foo& operator=(Foo&& rhs) & noexcept {}

实现起来很简单,它提供了更好的界面设计,因为它可以分配给任何其他值,因为它不是有意义的,也可能是错误的来源。

但是,应该注意的是,错误地写a + b = c的可能性非常低。编译器生成的赋值运算符也不是左值引用限定的,我们可以用标准类型编写a + b = c,例如使用std::stringstd::complex