三元运算符评估顺序 [英] Ternary operator evaluation order

查看:97
本文介绍了三元运算符评估顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class Foo {
  public:
  explicit Foo(double item) : x(item) {}

  operator double() {return x*2.0;}

  private:
  double x;
}

double TernaryTest(Foo& item) {
  return some_condition ? item : 0;
}

Foo abc(3.05);
double test = TernaryTest(abc);

在上面的示例中,如果some_condition为true,为什么test等于6(而不是6.1)?

In the above example, why is test equal to 6 (instead of 6.1) if some_condition is true?

更改如下所示的代码将返回6.1的值

Changing the code like below returns value of 6.1

double TernaryTest(Foo& item) {
  return some_condition ? item : 0.0; // note the change from 0 to 0.0
}

例如)Foo :: operator double的返回值强制转换为int,然后返回double。为什么?

It seems that (in the original example) the return value from Foo::operator double is cast to an int and then back to a double. Why?

推荐答案

条件运算符会双向检查转换。在这种情况下,由于构造函数是显式的(因此?:不明确),因此从 Foo 的转换使用 int ,并使用转换为 double 的转换函数:可行,因为在应用转换函数后,标准转换将 double 转换为 int (截断)。在您的情况下,?:的结果为 int ,其值为 6

The conditional operator checks conversions in both directions. In this case, since your constructor is explicit (so the ?: is not ambiguous), the conversion from Foo to int is used, using your conversion function that converts to double: That works, because after applying the conversion function, a standard conversion that converts the double to int (truncation) follows. The result of ?: in your case is int, and has the value 6.

在第二种情况下,由于操作数的类型为 double ,因此没有这样的尾随转换为 int 发生,因此结果类型?:的类型为 double 期望值。

In the second case, since the operand has type double, no such trailing conversion to int takes place, and thus the result type of ?: has type double with the expected value.

要了解不必要的转换,您必须了解像?:: 这样的表达式是上下文 -free:在确定其值和类型时,编译器不会将其视为返回的函数的 return 的操作数。 double

To understand the "unnecessary" conversions, you have to understand that expressions like your ?: are evaluated "context-free": When determining the value and type of it, the compiler doesn't consider that it's the operand of a return for a function returning a double.

编辑:如果构造函数是隐式的,会发生什么? >? ?:表达式将是模棱两可的,因为您可以将 int 转换为类型为 Foo (使用构造函数),将 Foo 转换为右值 int (使用转换功能)。标准说

What happens if your constructor is implicit? The ?: expression will be ambiguous, because you can convert an int to an rvalue of type Foo (using the constructor), and a Foo to an rvalue of type int (using the conversion function). The Standard says


使用此过程,确定是否可以转换第二个操作数以匹配第三个操作数,以及是否确定第三个操作数可以转换为匹配第二个操作数。如果两者都可以转换,或者一个可以转换但转换不明确,则说明程序格式错误。

Using this process, it is determined whether the second operand can be converted to match the third operand, and whether the third operand can be converted to match the second operand. If both can be converted, or one can be converted but the conversion is ambiguous, the program is ill-formed.






说明您的 Foo 如何转换为 int 的段落:

5.16 / 3 关于条件? E1:E2


否则,如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能cv限定的类类型),尝试将每个操作数转换为另一个操作数的类型。 [...]如果将E1隐式转换为表达式E2(如果将E2转换为右值(或者如果E2是右值,则具有它的类型)),则可以将E1转换为匹配E2。

Otherwise, if the second and third operand have different types, and either has (possibly cv-qualified) class type, an attempt is made to convert each of those operands to the type of the other. [...] E1 can be converted to match E2 if E1 can be implicitly converted to the type that expression E2 would have if E2 were converted to an rvalue (or the type it has, if E2 is an rvalue).

4.3 关于隐式转换:


当且仅当声明 T t = e; 很好时,表达式e才能隐式转换为T类型。

An expression e can be implicitly converted to a type T if and only if the declaration T t = e; is well-formed, for some invented temporary variable t.

8.5 / 14 初始化( T t = e;


如果源类型是(可能是cv合格的类类型),则考虑转换函数。列举了适用的转换函数(13.3.1.5),并通过过载分辨率(13.3)选择了最佳转换函数。如此选择的用户定义转换将被调用,以将初始化器表达式转换为正在初始化的对象。如果转换无法完成或模棱两可,则初始化格式错误。

If the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion functions are enumerated (13.3.1.5), and the best one is chosen through overload resolution (13.3). The user-defined conversion so selected is called to convert the initializer expression into the object being initialized. If the conversion cannot be done or is ambiguous, the initialization is ill-formed.

13.3.1.5 关于转换函数候选


考虑了S及其基类的转换函数。那些未隐藏在S中并产生T型或可以通过标准转换序列(13.3.3.1.1)转换为T型的类型的候选函数。

The conversion functions of S and its base classes are considered. Those that are not hidden within S and yield type T or a type that can be converted to type T via a standard conversion sequence (13.3.3.1.1) are candidate functions.

这篇关于三元运算符评估顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆