有没有人发现需要将复制赋值运算符的返回参数声明为 const?

发布于 08-28 16:57 字数 247 浏览 7 评论 0原文

复制赋值运算符具有通常的签名:

    my_class & operator = (my_class const & rhs);

以下签名有任何实际用途吗?

    my_class const & operator = (my_class const & rhs);

您只能定义其中之一,但不能同时定义两者。

The copy assignment operator has the usual signature:

    my_class & operator = (my_class const & rhs);

Does the following signature have any practical use?

    my_class const & operator = (my_class const & rhs);

You can only define one or the other, but not both.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

最近可好2024-09-04 16:57:01

将复制赋值的返回类型设置为非常量引用的主要原因是它是标准中“可赋值”的要求。

如果您将返回类型设置为 const 引用,那么您的类将无法满足在任何标准库容器中使用的要求。

The principle reason to make the return type of copy-assignment a non-const reference is that it is a requirement for "Assignable" in the standard.

If you make the return type a const reference then your class won't meet the requirements for use in any of the standard library containers.

可可2024-09-04 16:57:01

不要那样做。它阻止客户编写类似以下内容的内容:

(a = b).non_const_method();

而不是较长的形式:

a = b;
a.non_const_method();

虽然您可能不喜欢速记风格,但实际上由库的用户决定他们想要如何编写代码。

Don't do that. It prevent a client from writing something like:

(a = b).non_const_method();

instead of the longer form:

a = b;
a.non_const_method();

While you may not like the shorthand style, it's really up to the user of the library to decide how they want to write the code.

人海汹涌2024-09-04 16:57:01

一个答案反映了在C++中重载赋值运算符

返回一个const& 仍然允许赋值链:

a = b = c;

但将不允许一些更不寻常的用途:

(a = b) = c;

请注意,这使得赋值运算符的语义类似于 C 中的语义,其中 返回的值>= 运算符不是左值。在 C++ 中,标准对其进行了更改,因此 = 运算符返回左操作数的类型,因此结果是左值。但是正如史蒂夫·杰索普在另一个答案的评论中指出的,虽然使得编译器

(a = b) = c;

甚至可以接受内置函数,结果是内置函数的未定义行为,因为 a 被修改了两次而没有中间序列点。对于带有 operator=() 的非内置函数,可以避免这个问题,因为 operator=() 函数调用充当序列点。

我认为返回 const& 没有问题,除非您想专门允许左值语义(并设计类以确保它与这些语义一起合理地运行)。如果您的用户想要对 operator=() 的结果做一些不寻常的事情,我希望该类禁止它,而不是希望它偶然而不是设计正确。

还。请注意,当你说:

您只能定义其中之一,但不能同时定义两者。

这是因为 C++ 中的函数签名没有考虑返回值类型。然而,您可以有多个 operator=() 赋值运算符,它们采用不同的参数并返回适合参数类型的不同类型:

my_class& operator=( my_class& rhs);
my_class const& operator=(my_class const& rhs);

但我不完全确定这会给您带来什么。在这两种情况下,分配给的对象(可能是返回的引用)都是非常量的,因此没有逻辑理由仅仅因为 < 的右侧就返回 const& code>= 是 const。但也许我错过了一些东西......

An answer that mirrors one from Overloading assignment operator in C++:

Returning a const& will still allow assignment chaining:

a = b = c;

But will disallow some of the more unusual uses:

(a = b) = c;

Note that this makes the assignment operator have semantics similar to what it has in C, where the value returned by the = operator is not an lvalue. In C++, the standard changed it so the = operator returns the type of the left operand, so the result is an lvalue. But as Steve Jessop noted in a comment to another answer, while that makes it so the compiler will accept

(a = b) = c;

even for built-ins, the result is undefined behavior for built-ins since a is modified twice with no intervening sequence point. That problem is avoided for non-builtins with an operator=() because the operator=() function call serves as a sequence point.

I see no problem returning a const& unless you want to specifically allow the lvalue semantics (and design the class to ensure it acts sensibly with those semantics). If you're users want to do something unusual with the result of operator=(), I'd prefer that the class disallow it rather than hope it gets it right by chance instead of design.

Also. note that while you said:

You can only define one or the other, but not both.

that's because the function signature in C++ doesn't take into account the return value type. You could however have multiple operator=() assignement operatiors that take different parameters and return different types appropriate to the parameter types:

my_class& operator=( my_class& rhs);
my_class const& operator=(my_class const& rhs);

I'm not entirely sure what this would buy you though. The object being assigned to (that is presumably the reference being returned) is non-const in both cases, so there's no logical reason to return a const& just because the righ-hand-side of the = is const. But maybe I'm missing something...

药祭#氼2024-09-04 16:57:01

《Effective C++》解释说,这会破坏与 C++ 内置类型的兼容性。

你可以用普通的 int 来做到这一点:

(x = y) = z;

所以他认为,无论这看起来多么愚蠢,人们也应该能够对自己的类型做同样的事情。

这个例子在第二版中有,但在第三版中不再有。然而,第三版第 10 条中的这句话仍然说明了同样的情况:

[...] 赋值返回对其左侧参数的引用,这是在为类实现赋值运算符时应遵循的约定:

class Widget {
public:
  ...
  Widget& operator=(const Widget& rhs)   // return type is a reference to
  {                                      // the current class
  ...
  return *this;                        // return the left-hand object
  }
  ...
};

Effective C++ explains that this would break compatibility with the built-in types of C++.

You can do this with plain ints:

(x = y) = z;

so he reasons, however silly this looks like, one should be able to do the same with one's own type as well.

This example is there in 2nd Edition, although not anymore in the 3rd. However, this quote from 3rd Ed., Item 10 tells the same still:

[...] assignment returns a reference to its left-hand argument, and that's the convention you should follow when you implement assignment operators for your classes:

class Widget {
public:
  ...
  Widget& operator=(const Widget& rhs)   // return type is a reference to
  {                                      // the current class
  ...
  return *this;                        // return the left-hand object
  }
  ...
};
哆兒滾2024-09-04 16:57:01

为什么每个人都痴迷于(a = b) = c?这是偶然写的吗?

更改分配结果可能会产生一些不可预见的效用。你不能只是对那些看起来很有趣的虚构例子制定武断的规则。从语义上讲,没有理由它应该是 const,因此不要将其声明为 const 以产生词法副作用。

下面是一个合理的代码示例,它因 const & 赋值而中断:

my_class &ref = a = b;

Why is everyone obsessing over (a = b) = c? Has that ever been written by accident?

There is probably some unforeseen utility of the result of assignment being altered. You don't just make arbitrary rules against made-up examples that look funny. Semantically there is no reason that it should be const, so do not declare it const for lexical side effects.

Here is an example of somewhat reasonable code that breaks for const & assignment:

my_class &ref = a = b;
三生殊途2024-09-04 16:57:01

与 const 的任何其他用法一样,const 是默认值,除非您确实想让用户更改。

As in any other usage of const, const is the default, unless you really want to let the user change.

小傻瓜2024-09-04 16:57:01

是的,它应该是const。否则客户可以这样做:

class MyClass
{
public:
      MyClass & operator = (MyClass const & rhs);
}

void Foo() {
    MyClass a, b, c;
    (a = b) = c; //Yikes!
}

Yes, it should be const. Otherwise clients can do this:

class MyClass
{
public:
      MyClass & operator = (MyClass const & rhs);
}

void Foo() {
    MyClass a, b, c;
    (a = b) = c; //Yikes!
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文