c++ - 令人不安的评估顺序

标签 c++ expression-evaluation

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

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

据我所知,v.end()(在 rhs 上)可能会在 调用 std::删除_if。这在这里不是问题,因为 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 被调用之后被调用;这意味着当调用 print_rhs 时,data.v1。尽管如此,由于 data.value() 可能会在 之前计算,因此 0 是可能的输出。

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

我的问题是:

  • 是否曾在 C++ 委员会中讨论或建议过该更改?
  • 您认为它会带来什么问题吗?

最佳答案

Has that change ever been discussed or suggested in a C++ committee?

可能。

Do you see any problem it could bring?

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

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

相关文章:

c++ - 为什么 `std::ranges::clamp`会如此严格地限制投影数量?

c++ - 为什么这在 C 中编译而不是 C++ (sigaction)?

c - C 中的表达式求值

ANTLR : expression evaluator, split 和战俘

language-agnostic - 评估骰子滚动符号字符串

c++ - 没有匹配的调用函数

c++ - 为什么 %p 不显示指针的全宽?

c++ - 在 Qt 5.6 中休眠

c# - 在 Irony 中定义常量和运算符

c++ - 使用不同的符号表重新计算 Boost Spirit 解析的属性的最有效方法是什么?