简体   繁体   English

从带有移动分配的算术运算符重载返回const值

[英]Returning const value from arithmetic operator overload with move assignment

Let's say I have the following minimal example class: 假设我有以下最小示例类:

#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;
}

This prints move as expected. 此打印move按预期方式。 Now according to Effective C++ Item 3, I should return const Foo from operator+ to avoid construct like a + b = c , ie: 现在根据有效的C ++项目3,我应该从operator+返回const Foo以避免类似a + b = c构造,即:

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

Unfortunately, this suddenly starts calling copy assignment instead of move assignment operator. 不幸的是,这突然开始调用副本分配而不是移动分配运算符。 [I'm using gcc 4.8.4 on Ubuntu, but it is probably nothing related to compiler] [我在Ubuntu上使用gcc 4.8.4,但这可能与编译器无关]

How can I ensure that a + b = c fails to compile and in the same time move assignment is called for a = b + c ? 如何确保a + b = c编译失败并且同时为a = b + c调用移动分配? Or with the introduction of move semantics, is there no way to achieve both of them in the same time? 还是随着移动语义的引入,没有办法同时实现它们吗?

I have ended up using lvalue reference qualifier as pointed by Caninonos in comment and by max66 in now deleted answer (but 10k users can see it). 我最终使用了Caninonos在注释中指出的左值引用限定符,并在现在已删除的答案中使用了max66(但是1万用户可以看到它)。

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

It is simple to implement and it provides a better interface design since assignment to anything other that lvalue doesn't sound meaningful and a possible source of bug. 它的实现很简单,并且提供了更好的界面设计,因为分配给左值听起来毫无意义的其他东西以及可能的错误源。

However, it should be noted that the possibility of writing a + b = c by mistake is very low. 但是,应注意,错误写入a + b = c的可能性非常低。 Also compiler generated assignment operators are not lvalue reference qualified and we can write a + b = c with standard types, eg with std::string or with std::complex . 同样,编译器生成的赋值运算符不是左值引用限定的,我们可以使用标准类型(例如,使用std::stringstd::complex编写a + b = c

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

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