返回类型'?:'(三元条件运算符)

Yol*_*ola 207 c++ types reference conditional-operator lvalue

为什么第一个返回引用?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;
Run Code Online (Sandbox Code Playgroud)

而第二个不?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;
Run Code Online (Sandbox Code Playgroud)

实际上,第二个根本没有编译 - "没有左边的赋值".

CB *_*ley 173

表达式没有返回类型,它们具有类型,并且 - 在最新的C++标准中已知 - 值类别.

条件表达式可以是左值右值.这是它的价值类别.(这有点简化,C++11我们有lvalues,xvalues和prvalues.)

在非常宽泛和简单的术语中,左值是指内存中的对象,而右值只是一个值,可能不一定附加到内存中的对象.

赋值表达式为对象赋值,因此赋值的对象必须是左值.

对于条件表达式(?:)是一个左值(再次,在广泛的和简单的术语),所述第二和第三操作数必须是左值的相同类型的.这是因为条件表达式的类型和值类别是在编译时确定的,并且必须是适当的,无论条件是否为真.如果必须将其中一个操作数转换为不同的类型以匹配另一个操作数,则条件表达式不能是左值,因为此转换的结果不是左值.

ISO/IEC 14882:2011参考:

3.10 [basic.lval]左值和右值(关于值类别)

5.15 [expr.cond]条件运算符(条件表达式具有的类型和值类别的规则)

5.17 [expr.ass]赋值和复合赋值运算符(要求赋值的lhs必须是可修改的左值)

  • 在阅读xvalue和prvalue时(因为我在回答之前没有听说过)我遇到了这个方便的帖子:http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues -glvalues-和prvalues (3认同)

Xeo*_*Xeo 57

三元?:表达式的类型是其第二和第三个参数的常见类型.如果两种类型相同,则返回引用.如果它们可以相互转换,则选择一个,另一个转换(在这种情况下提升).由于您无法将lvalue引用返回到临时(转换/提升的变量),因此其类型是值类型.

  • @Yola:由于类型是C++中的编译时概念,表达式的实际返回*值*无关紧要. (3认同)

Fil*_*efp 19

它不能返回左值,因为它必须隐式地提升x匹配类型的类型y(因为两边的:类型不同),并且必须创建一个临时值.


标准说什么?(n1905)

表达式5.17赋值和复合赋值运算符

5.17/3

如果第二个和第三个操作数具有不同的类型,并且具有(可能是cv-qualified)类类型,则尝试将每个操作数转换为另一个操作数的类型.确定类型T1的操作数表达式E1是否可以转换为匹配类型T2的操作数表达式E2的过程定义如下:

- 如果E2是左值:如果可以将E1隐式转换(第4节)到类型"引用到T2",则E1可以转换为匹配E2,但受转换引用必须直接绑定的约束(8.5.3)到E1.

- 如果E2是右值,或者上述转换无法完成:

- 如果E1和E2具有类类型,并且底层类类型相同或者一个是另一个类的基类:如果T2的类与类型相同,则可以转换为E1以匹配E2,或者基类,T1的等级和T2的cv资格是与cv资格相同的cv资格,或者更高的cv资格.如果应用转换,则将E1更改为类型T2的右值,该值仍然引用原始源类对象(或其相应的子对象).[ 注意:即没有复制.- 结束注释 ]通过从E1复制初始化T2类型的临时值并将该临时值用作转换后的操作数.

否则(即,如果E1或E2具有非类型类型,或者它们都具有类类型但基础类不是相同的或者是另一个的基类):如果E1可以是E1,则可以转换为匹配E2如果E2被转换为rvalue(或者它具有的类型,如果E2是rvalue),则隐式转换为表达式E2将具有的类型.

使用该过程,确定是否可以转换第二操作数以匹配第三操作数,以及是否可以转换第三操作数以匹配第二操作数.如果两者都可以转换,或者一个可以转换,但转换不明确,则程序格式不正确.如果两者都不能被转换,则操作数保持不变并且如下所述执行进一步检查.如果只能进行一次转换,则将该转换应用于所选操作数,并使用转换后的操作数代替本节其余部分的原始操作数.


5.17/4

如果第二个和第三个操作数是左值并且具有相同的类型,则结果是该类型并且是左值,如果第二个或第三个操作数是位字段,或者两者都是位,则它是位字段领域.


5.17/5

否则,结果是右值.如果第二个和第三个操作数不具有相同的类型,并且具有(可能是cv限定的)类类型,则使用重载决策来确定要应用于操作数的转换(如果有)(13.3.1.2,13.6) .如果重载决策失败,则程序格式错误.否则,应用如此确定的转换,并使用转换的操作数代替本节其余部分的原始操作数.