多重赋值(a = b) = c语法是如何工作的?

How does multiple assignment (a = b) = c syntax work?

本文关键字:何工作 工作 赋值 语法      更新时间:2023-10-16

如果a, bcint s或任何其他基本类型,那么像(a = b) = c;这样的语句如何在c++中工作?

赋值表达式a = b在C中不是左值,但在c++中是:

  • C11, 6.5.14(赋值操作符):

    赋值操作符将值存储在左操作数指定的对象中。赋值表达式具有赋值后左操作数的值,但不是左值
  • c++ 14, 5.18 [expr。(赋值和复合赋值操作符):

    赋值操作符(=)和复合赋值操作符都是由右向左组合的。它们都需要一个可修改的左值作为左操作数,并返回一个指向左操作数的左值

在c++从C进化而来的过程中,有几个表达式被赋予了"左值感知"功能,因为左值在c++中比在C中重要得多。在C中,一切都是微不足道的(用c++的话说,都是微不足道的可复制和微不足道的可破坏),所以左值到右值的转换(或C所说的"左值转换")并不痛苦。在c++中,复制和析构是非常重要的概念,通过使表达式保持左值性,可以避免大量一开始就不需要的复制和析构。

另一个例子是条件表达式(a ? b : c),它在C中不是左值,但在c++中可以是左值。

这种语言演变的另一个有趣的产物是C有四个定义良好的存储持续时间(自动、静态、线程局部和动态),但在c++中这变得更加混乱,因为临时对象在c++中是一个重要的概念,几乎需要自己的存储持续时间。(例如Clang内部有第五个"完整表达式"存储持续时间。)临时值当然是左值到右值转换的结果,因此通过避免转换,可以少担心一件事。

(请注意,所有这些讨论只适用于各自的核心语言表达式。c++还具有操作符重载的独立的、不相关的特性,该特性生成函数调用表达式,该表达式具有函数调用的所有常用语义,除了语法之外与操作符无关。例如,您可以定义一个重载的operator=,它返回一个右值或void(如果您愿意的话)

在c++中,对于内置类型,a = b的结果是对a的引用;您可以为该引用赋值,就像对任何其他引用一样。因此,(a = b) = cb的值赋给a,然后将c的值赋给a

对于用户定义类型,这可能不适用,尽管通常的习惯用法是赋值操作符返回对左参数的引用,因此用户定义类型的行为模仿内置类型的行为:

struct S {
    S& operator=(const S& rhs) {
        return *this;
    }
};

现在,S a, b, c; (a = b) = c;意味着调用a.operator=(b),返回对a的引用;然后调用S::operator=的结果和c,有效地调用a.operator=(c)

(a = b) = c在c++中是有效的语句。这里'='作为赋值操作符。这里,b的值将被赋给ac的值将被赋给a,从右向左优先。

例如:

int a = 5;
int b = 2;
int c = 7;
int answer = (a = b) = c;
cout << answer << endl;
输出:

7

以下是一些猜测,如果我错了,请纠正我。

当他们发明操作符重载时,他们必须为任何类T提供一个标准的赋值操作符的一般形式。例如:

T& T::operator=(T);
T& T::operator=(const T&);

在这里,它返回一个对T的引用,而不仅仅是T,以使x = (y = z)这样的三部分赋值高效,而不需要副本。

它可以返回constT的引用,这将使不需要的赋值(a = b) = c出错。我猜想他们没有使用这个有两个原因:

  1. 更短的代码-不需要一直写所有这些const (const的细节-正确性当时还不清楚)
  2. 更灵活-允许像(a = b).print()这样的代码,其中print是一个非const方法(因为程序员懒惰/忽视const的正确性)

基本类型(不是class类型)的语义被推断为:

int& operator=(int&, int); // not real code; just a concept

"返回类型"不是const int&,所以它匹配class es的模式。因此,如果有缺陷的(a = b) = c代码对用户定义类型有效,那么它也应该对内置类型有效,这是c++设计原则所要求的。一旦你记录了这些东西,你就不能改变它了,因为向后兼容性。