【问题标题】:C++ function evaluation order in assignment operator赋值运算符中的 C++ 函数求值顺序
【发布时间】:2012-01-07 20:59:13
【问题描述】:
int& foo() {
   printf("Foo\n");
   static int a;
   return a;
}

int bar() {
   printf("Bar\n");
   return 1;
}

void main() {
   foo() = bar();
}

我不确定应该先评估哪一个。

我在VC中试过先执行bar函数。然而,在 g++ (FreeBSD) 的编译器中,它给出了首先评估的 foo 函数。

很多有趣的问题来源于上面的问题,假设我有一个动态数组(std::vector)

std::vector<int> vec;

int foobar() {
   vec.resize( vec.size() + 1 );
   return vec.size();
}

void main() {
   vec.resize( 2 );
   vec[0] = foobar();
}

基于先前的结果,vc 计算 foobar(),然后执行向量 operator[]。在这种情况下是没有问题的。但是,对于 gcc,由于正在评估 vec[0] 并且 foobar() 函数可能导致更改数组的内部指针。执行 foobar() 后 vec[0] 可以失效。

这是否意味着我们需要将代码分开,这样

void main() {
   vec.resize( 2 );
   int a = foobar();
   vec[0] = a;
}

【问题讨论】:

  • +2,这是一个有趣的问题;这是我以前从未考虑过的事情。显然,如果你开始使用这样的代码,你就有麻烦了 :)
  • +1。这真是一个有趣的问题;不仅如此,这个问题被问得非常好。一个写得很好的问题。
  • 我今天遇到了一个有趣的例子:auto_ptr&lt;int&gt; p(new int); smart_map&lt;int,int*&gt; m; m[1]=p.release(); 如果您认为smart_map::operator[] 可能会抛出,您可能会遇到auto_ptr 释放其所有权但地图从未假定所有权,在 RHS 在 LHS 之前评估的情况下。 (假设smart_map类似于STL map,只是它在销毁时删除了每个键/值对的指针值。)

标签: c++ function evaluation


【解决方案1】:

C++ 中控制是否定义评估顺序的概念称为sequence point

基本上,在一个序列点,保证该点之前的所有表达式(具有可观察到的副作用)都已被评估,并且尚未评估该点之后的任何表达式。

尽管有些人可能会感到惊讶,但赋值运算符并不是一个序列点。所有序列点的完整列表在Wikipedia article

【讨论】:

  • ...称为序列点。从今年开始,我们使用 sequenced before / sequenced after
【解决方案2】:

表达式的求值顺序是未指定的行为
这取决于编译器选择评估的顺序。

您应该避免编写这样的代码。
虽然如果没有副作用,那么顺序应该无关紧要。

如果顺序很重要,那么您的代码错误/不可移植/可能会在不同的编译器中给出不同的结果**。

【讨论】:

    【解决方案3】:

    在这种情况下,评估顺序将是未指定的。不要写这样的代码

    类似的例子here

    【讨论】:

      猜你喜欢
      • 2021-07-12
      • 1970-01-01
      • 2014-12-11
      • 2012-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-06
      • 1970-01-01
      相关资源
      最近更新 更多