如果一个语句(a = b) = c;在C++中工作,假设是什么a,b或者c是ints或任何其他原始类型?
Ker*_* SB 57
赋值表达式a = b不是C中的左值,但它在C++中:
C11,6.5.14(分配操作员):
赋值运算符将值存储在左操作数指定的对象中.赋值表达式在赋值后具有左操作数的值,但不是左值.
C++ 14,5.18 [expr.ass](赋值和复合赋值运算符):
赋值运算符(
=)和复合赋值运算符都是从右到左分组.所有都需要一个可修改的左值作为左操作数,并返回一个左值操作数的左值.
在C语言从C语言的演变中,有几个表达式被称为"左值感知",因为它在C++中比在C中更重要.在C语言中,一切都是微不足道的(通常是可复制的和平凡的可破坏的,所有这些都在C++的话,所以左值到右值的转换(或"左值转换",如C调用它们)并不痛苦.在C++中,复制和破坏是非平凡的概念,通过使表达式保持左值,可以避免许多复制和破坏,这是从来没有必要开始的.
另一个例子是条件表达式(a ? b : c),它不是C中的左值,但可以是C++中的左值.
这种语言演变的另一个有趣的假象是C有四个明确定义的存储持续时间(自动,静态,线程局部,动态),但在C++中这变得更加混乱,因为临时对象在C++中几乎是一个非平凡的概念要求自己的存储时间.(例如Clang内部有第五个"完整表达"存储持续时间.)临时数据当然是左值到右值转换的结果,所以通过避免转换,可以少担心一件事.
(请注意,所有这些讨论仅适用于相应的核心语言表达式.C++还具有独立的,无关的运算符重载特性,它产生函数调用表达式,它具有函数调用的所有常用语义,与之无关.除了语法之外的运算符.例如,您可以定义一个operator=返回prvalue 的重载或者void如果您愿意的话.)
Pet*_*ker 22
非正式地,在C++中,对于内置类型,结果a = b是引用a; 您可以为该引用分配值,就像使用任何其他引用一样.因此(a = b) = c赋值bto a,然后赋值cto a.
对于用户定义的类型,这可能不适用,尽管通常的习惯用法是赋值操作符返回对左侧参数的引用,因此用户定义类型的行为模仿内置类型的行为:
struct S {
S& operator=(const S& rhs) {
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,S a, b, c; (a = b) = c;意味着调用a.operator=(b),它返回一个引用a; 然后调用S::operator=该结果,并c有效地调用a.operator=(c).
| 归档时间: |
|
| 查看次数: |
5072 次 |
| 最近记录: |