当我使用自己喜欢的容器工作时,我倾向于链接操作。例如,在著名的Erase–remove idiom中:

v.erase( std::remove_if(v.begin(), v.end(), is_odd), v.end() );

根据我对求值顺序的了解,可能在调用v.end()之前先对std::remove_if(在rhs上)进行求值。这不是问题,因为std::remove*仅对 vector 进行混洗,而不会更改其最终迭代器。

但这可能会导致真正令人惊讶的构造,例如(demo):
#include <iostream>

struct Data
{
    int v;
    int value() const { return v; }
};

auto inc(Data& data)           { return ++data.v; }
void print_rhs(int, int value) { std::cout << value << '\n'; }

int main()
{
    Data data{0};
    print_rhs(inc(data), data.value()); // might print 0
}

这是令人惊讶的,因为在调用print_rhs之后调用了inc;这意味着data.v被调用时1print_rhs。但是,由于data.value()可能在之前进行了评估,因此0是可能的输出。

我认为,如果评估顺序不那么令人惊讶,那可能是一个不错的改进。特别是如果具有副作用的函数的参数在没有副作用的函数之前进行了评估。

我的问题是:
  • C++委员会是否曾经讨论过或建议过这种更改?
  • 您看到它可能带来的任何问题吗?
  • 最佳答案



    大概。



    是的。它可以减少当今存在的优化机会,并且除了能够编写更多的单行代码之外,没有带来直接的好处。但是无论如何,单行并不是一件好事,因此,这个提议可能永远不会超越-99 points

    关于c++ - 令人不安的评估顺序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52203232/

    10-13 05:37