【问题标题】:The evaluation of 'if' expressions'if' 表达式的评估
【发布时间】:2012-04-29 03:03:08
【问题描述】:

考虑一下我有以下几点:

edge some_edge;
std::priority_queue<edge> my_queue;

即使队列可能为空,写这样的“如果”是否安全?

if ((my_queue.size() > 0) && (my_queue.top().weight < some_edge.weight)) {
    do_something;
}

这个呢?

if ((my_queue.top().weight < some_edge.weight) && (my_queue.size() > 0)) {
    do_something;
}

如果左操作数的计算结果为假,则计算操作数之间的运算符为“and”的表达式是否停止?

【问题讨论】:

  • if 是 C++ 中的语句,而不是表达式。是的,短路评估需要 C++(只要不涉及重载的 operator&amp;&amp;operator||)。
  • 但是我们在这个上下文中讨论的评估是表达式,@Ildjarn。它们在“if”语句中的事实实际上并不相关。

标签: c++ if-statement short-circuiting


【解决方案1】:

C++ 中的if 语句是从左到右关联的,逻辑布尔运算符&amp;&amp;|| 是短路的,所以是的,像下面这样的语句是安全的,因为它保证您检查大小首先(假设这些运算符没有重载):

if(myqueue.size() > 0 && myqueue.top().whatever) {
    // ...
}

然而,相反的情况并非如此,因为您检查了size() 的返回值 弹出队列。

顺便说一句,std::priority_queue 提供了一个 empty() 函数,我/许多人更喜欢 size() &gt; 0,但这也有效。

if(!myqueue.empty() && myqueue.top().whatever()) {
    // ...
}

【讨论】:

  • IMO,这里最好不要提及关联性——评估顺序不是由关联性决定的,而是由序列点决定的。
【解决方案2】:

是的,这种行为是根据 C++ 标准得到保证的。

if (false && doSomething())

永远不会评估doSomething()

但是,如果您重载 operator&amp;&amp;,所有表达式都会被计算,因此这种行为可能会有所不同。这就是为什么触摸operator&amp;&amp; 是个坏主意。

您应该使用!empty() 而不是size() &gt; 0

【讨论】:

    【解决方案3】:

    这根本不是关于if,而是关于&amp;&amp;。逻辑运算符(&amp;&amp;||)首先计算其左操作数。然后当且仅当右操作数可以影响逻辑结果时,它们才会评估右操作数。

    &amp;&amp; 的情况下,如果左操作数的计算结果为false,则无论右操作数的值如何,结果都将为false,因此不会计算右操作数。

    对于||,如果左操作数的计算结果为true,则无论右操作数的值如何,结果都将为true,因此不会计算右操作数。

    无论&amp;&amp; 是否在if 语句的表达式中,这都是正确的。一些混淆代码通过将if (x) y; 转换为x &amp;&amp; y 来利用这一点。虽然不经常看到,但您可以|| 做同样的事情。

    【讨论】:

    • 嗯,它 关于 if 语句的,因为它必须保证从左到右执行才能使其正常工作,但是是的,更多的是与短路有关.
    • @EdS.:关键是if 只是评估一个表达式。表达式本身强制执行从左到右的评估,无论它是否在 if 语句中。
    【解决方案4】:

    此链接解释了并非所有运算符都如此,即使 && 也是如此。特别是,请注意在关联性与评估顺序的上下文中从左到右/从右到左之间的差异。 http://en.cppreference.com/w/cpp/language/eval_order

    【讨论】:

      【解决方案5】:

      布尔表达式是短路计算的,所以如果第一部分失败,第二部分将不会运行。所以第一个例子不会访问不存在的内存,但第二个会。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-15
        • 1970-01-01
        相关资源
        最近更新 更多