C++为什么赋值运算符应该返回 const ref 以避免 (a=b)=c

发布于 2024-10-12 03:59:08 字数 367 浏览 4 评论 0原文

我正在读一本关于 C++ 的书,更准确地说是关于运算符重载的书。

例子如下:

const Array &Array::operator=(const Array &right)
{
// check self-assignment
// if not self- assignment do the copying
return *this; //enables x=y=z
}

书中提供的关于返回const ref而不是ref的解释是为了避免诸如(x=y)=z之类的赋值。我不明白为什么我们应该避免这种情况。我知道在这个例子中 x=y 首先被评估,因为它返回一个 const 引用,所以 =z 部分无法执行。但为什么?

I am reading a book about C++ and more precisely about the operator overloading.

The example is the following:

const Array &Array::operator=(const Array &right)
{
// check self-assignment
// if not self- assignment do the copying
return *this; //enables x=y=z
}

The explanation provided by the book about returning const ref instead of ref is to avoid assignments such as (x=y)=z. I don't understand why we should avoid this. I understand that x=y is evaluated first in this example and since it returns a const reference the =z part cannot be executed. But why?

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

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

发布评论

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

评论(5

灼痛 2024-10-19 03:59:08

(x=y) 表示 x.operator=(y),它返回对象 x。因此,(x=y)=z 表示 (x.operator=(y)).operator=(z)。括号中的表达式将 x 设置为 y 并返回 x,然后外部位将 x 设置为 >z。它不会像您所期望的那样将 y 设置为 z,也不像表达式 x = y = z 那样。

这种行为是违反直觉的(赋值后它们应该都是相等的,对吧?);返回常量引用使其不可能并避免该问题。

(x=y) means x.operator=(y), which returns the object x. Therefore, (x=y)=z means (x.operator=(y)).operator=(z). The expression in parens sets x to y and returns x, and then the outer bit sets x to z. It does not set y to z as you might expect, and as the expression x = y = z does.

This behavior is counter-intuitive (they should all be equal after the assignment, right?); returning a const reference makes it impossible and avoids the problem.

后来的我们 2024-10-19 03:59:08

没有必要避免这种情况,除非本书的目标读者是通常在表示 x=y=z 时写成 (x=y)=z 的程序员。实际上,没有一个头脑正常的人会这么写,所以这种预防措施是完全没有必要的。它还禁止其他一些简洁的构造,例如 (x=y).nonConstMember(),几乎没有人编写这些构造,但在某些情况下可能有用(尽管它们不应该被过度使用) 。

@ybungalobil 是对的,买一本更好的书。

There is no need to avoid this, unless the book is aimed at programmers that commonly write (x=y)=z when they mean x=y=z. In practice, nobody in their right mind writes that, so the precaution is entirely unnecessary. It also forbids some other terse constructs, such as (x=y).nonConstMember(), that hardly anyone writes but that might be useful in some contexts (although they shouldn't be over-used).

@ybungalobill is right, get a better book.

有深☉意 2024-10-19 03:59:08

据我所知,在惯用的 C++ 中,赋值运算符不会返回 const 引用。标准类型也不返回 const 引用。

std::string a, b, c;
(a = b).clear(); // no objection from compiler

我的所有自定义赋值运算符都返回了非常量引用。

如有疑问,请检查标准库。它并不是完美无缺的,但它绝对可以正确地完成诸如此类的基本事情。

As far as I know, assignment operators do not return const references in idiomatic C++. The Standard types do not return const references either.

std::string a, b, c;
(a = b).clear(); // no objection from compiler

All of my custom assignment operators have returned a non-const reference.

When in doubt, check the Standard library. It's not flawless, but it definitely gets basic things like this correct.

孤城病女 2024-10-19 03:59:08

我会看看内置类型的行为。

定义您自己的类型时,最好使运算符的行为方式与内置类型相同。这使得您可以轻松采用您的类,而无需深入研究代码来了解它们的行为与预期不同的原因。

因此,如果我们看一下整数:

int main()
{
    int x = 5;
    int y = 6;
    int z = 7;

    (x = y) = z;
    std::cout << x << " " << y << " " << z << "\n";
}

这适用于 y 不变且 x 被分配 7 的情况。在您的代码中,我希望您的赋值运算符以相同的方式工作。标准赋值运算符定义:

Array& Array::operator=(Array const& rhs)
{
    /* STUFF */
    return *this;
}

应该可以做到这一点(假设 /* STUFF */ 是正确的)。

I would look at the behavior of the built-in types.

When defining your own types it is preferable that the operators behave the same way as the built-in types. This allows easy adoption of your classes without having to dig into your code to see why they behave differently from expected.

So if we look at integers:

int main()
{
    int x = 5;
    int y = 6;
    int z = 7;

    (x = y) = z;
    std::cout << x << " " << y << " " << z << "\n";
}

This works with y unchanged and x being assigned 7. In your code i would expect your assignment operator to work the same way. The standard assignment operator definition:

Array& Array::operator=(Array const& rhs)
{
    /* STUFF */
    return *this;
}

Should do that just fine (assuming /* STUFF */ is correct).

怎樣才叫好 2024-10-19 03:59:08

我能看到的唯一原因是这本书是为了向 C 程序员解释 C++ 而写的(或者是由对 C 的理解比对 C++ 的理解更好的作者编写的)。因为对于 C 程序员来说,表达式 (x = y) = z 对于内置类型无效,他可能会尝试使用其用户定义类型获得相同的行为。

但是,C 和 C++ 是不同的语言,并且在 C++ 中,表达式 (x = y) = z 即使对于内置类型也是有效的。因此,如果您希望用户定义类型具有相同的行为,则应在 operator = 中返回一个非常量引用。

我建议你买一本更好的书,一本不会混淆 C 和 C++ 的书。即使它们源自共同的基础,它们也不是相同的语言。

The only reason I can see is that this book was written to explain C++ to C programmers (or by an author whose C understanding is better than C++ understanding). Because for a C programmer, the expression (x = y) = z is invalid for built-in types, and he probably will to try to get the same behavior with its user-defined types.

However, C and C++ are different languages, and in C++ the expression (x = y) = z is valid even for built-in types. So if you want to have the same behavior for your user-defined types, you should return a non-const reference in the operator =.

I would advise you to get a better book, one that does not make the confusion between C and C++. They are not the same langages, even if they derive from a common base.

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