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

C++ ';?的返回类型:';(三元条件运算符),c++,types,reference,conditional-operator,lvalue,C++,Types,Reference,Conditional Operator,Lvalue,为什么第一个返回一个引用 int x = 1; int y = 2; (x > y ? x : y) = 100; 而第二个没有 int x = 1; long y = 2; (x > y ? x : y) = 100; 实际上,第二个根本没有编译——“不是赋值左边的左值”。三元?:表达式的类型是第二个和第三个参数的常见类型。如果两种类型相同,则返回一个引用。如果它们可以相互转换,则选择一个,转换另一个(在本例中升级)。由于无法将左值引用返回到临时变量(已转换/升级的变量),因此

为什么第一个返回一个引用

int x = 1;
int y = 2;
(x > y ? x : y) = 100;
而第二个没有

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

实际上,第二个根本没有编译——“不是赋值左边的左值”。

三元
?:
表达式的类型是第二个和第三个参数的常见类型。如果两种类型相同,则返回一个引用。如果它们可以相互转换,则选择一个,转换另一个(在本例中升级)。由于无法将左值引用返回到临时变量(已转换/升级的变量),因此其类型为值类型。

它无法返回左值,因为它必须隐式升级
x
的类型以匹配
y
的类型(因为
的两侧不是同一类型),因此,它必须创建一个临时的


标准怎么说?() 表达式5.17赋值运算符和复合赋值运算符

5.17/3

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

-如果E2是左值:如果E1可以隐式转换(第4条)为类型“引用T2”,则E1可以转换为与E2匹配的值,但在转换过程中,引用必须直接绑定(8.5.3)到E1

-如果E2为右值,或无法进行上述转换:

-如果E1和E2具有类类型,且基础类类型相同或其中一个是另一个的基类:如果T2的类与T1的类相同或基类相同,且T2的cv鉴定与T1的cv鉴定相同,或cv鉴定大于,T1的简历资格。如果应用了转换,E1将更改为类型为T2的右值,该右值仍然引用原始源类对象(或其适当的子对象)。[注意:也就是说,不进行复制。-结束注意]通过复制从E1初始化T2类型的临时变量,并将该临时变量用作转换的操作数

否则(即,如果E1或E2具有非类类型,或者如果它们都具有类类型,但基础类既不相同,也不是一个或另一个的基类):如果E1可以隐式转换为表达式E2在E2转换为右值时所具有的类型,则可以将E1转换为与E2匹配的类型(或其类型,如果E2是右值)

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


5.17/4

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


5.17/5

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


表达式没有返回类型,它们有一个类型,正如在最新C++标准中所知道的,一个值类别。 条件表达式可以是左值或右值。这是它的值类别。(这有点简化,在
C++11
中,我们有左值、xvalue和prvalue。)

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

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

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

ISO/IEC 14882:2011参考文献:

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

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

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


真的很好,很快回答:)但是,如果你给这个参考(不是C++参考,而是网络参考:D),我会更愉快的。Yola:因为C++中的编译类型是编译时概念,表达式的实际返回值并不重要。您没有得到引用,就得到LValue.@ Xeo:不是在C++中。