具有无效类型的分支的三元运算符

时间:2017-04-03 17:17:55

标签: c++ compiler-optimization conditional-operator

使用返回void的函数的三元运算符是否安全?像这样:

void foo1(){}
void foo2(){}

//////////////

bool to_use_1 = ....;
to_use_1 ? foo1() : foo2();

编译器可以删除此代码吗?假设它会将这些函数视为纯函数,并执行删除这些调用的积极优化

1 个答案:

答案 0 :(得分:7)

首先,编译器将/应该从逻辑上“删除”任何具有可观察效果的调用( copy elision 除外)。无论优化模式多么激进,这都不是它允许做的事情。

事实上,C ++标准明确允许条件运算符的操作数结果为void,因此这是预期且安全的。但是,它必须两者

  

[C++14: 5.16/1]:条件表达式从右到左分组。第一个表达式在上下文中转换为bool(第4条)。 对其进行评估,如果为真,则条件表达式的结果为第二个表达式的值,否则为第三个表达式的值。只计算第二个和第三个表达式中的一个。在与第二个或第三个表达式相关的每个值计算和副作用之前,对与第一个表达式相关的每个值计算和副作用进行排序。

     

[C++14: 5.16/2]:如果第二个或第三个操作数的类型为void,则以下之一应保留:

     
      
  • 第二个或第三个操作数(但不是两个)是(可能带括号的) throw-expression (15.1);结果是另一个的类型和价值类别。

  •   
  • 第二个和第三个操作数都具有类型void;结果是void类型并且是prvalue。 [注意:这包括两个操作数都是 throw-expressions 的情况。 -end note]

  •   

从技术上讲,这句话(在其关于“值”的讨论中)并没有直接说明完全评估第二和第三个表达式中的一个,即使这些评价没有“价值” 。但从分析的角度来看,它基本上是无可争辩的。这里可以 进行编辑改进。

请注意,这些都不能保证您的计算机在执行期间实际跳转到foo1foo2;在您给出的具体示例中,编译器可以立即看到两个函数都是完全空的,并优化掉整行代码。但这不会影响程序的语义,也不会特定于使用条件运算符。