通过移动分配从算术运算符过载中返回const值

Returning const value from arithmetic operator overload with move assignment

本文关键字:返回 const 运算符 移动 分配      更新时间:2023-10-16

假设我有以下最小示例类:

#include <iostream>
class Foo {
public:
    Foo() = default;
    Foo(const Foo&) = default;
    Foo(Foo&&) noexcept = default;
    Foo& operator=(const Foo& rhs) {
        std::cout << "copyn";
        return *this;
    }
    Foo& operator=(Foo&& rhs) noexcept {
        std::cout << "moven";
        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。现在根据有效的C 项目3,我应该从operator+返回const Foo,以避免像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的移动分配?或者随着移动语义的引入,是否可以同时实现这两个?

我最终使用了caninonos在评论中指出的LVALUE参考预选赛,而Max66现在已删除答案(但是10K用户可以看到(。

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

实现很容易实现,它提供了更好的接口设计,因为分配了lvalue听起来没有有意义的其他任何内容。

但是,应该注意的是,错误地编写a + b = c的可能性非常低。编译器生成的分配运营商也不是LVALUE参考资格,我们可以使用标准类型编写a + b = c,例如使用std::string或使用std::complex