11
int& foo() {
   printf("Foo\n");
   static int a;
   return a;
}

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

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

I am not sure which one should be evaluated first.

I have tried in VC that bar function is executed first. However, in compiler by g++ (FreeBSD), it gives out foo function evaluated first.

Much interesting question is derived from the above problem, suppose I have a dynamic array (std::vector)

std::vector<int> vec;

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

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

Based on previous result, the vc evaluates the foobar() and then perform the vector operator[]. It is no problem in such case. However, for gcc, since the vec[0] is being evaluated and foobar() function may lead to change the internal pointer of array. The vec[0] can be invalidated after executation of foobar().

Is it meant that we need to separate the code such that

void main() {
   vec.resize( 2 );
   int a = foobar();
   vec[0] = a;
}
Yiu Fai
  • 111
  • 1
  • 4
  • 4
    +2, that's an interesting question; it's something I've never considered before. Obviously you're in trouble if you start using code like that anyway :) – Chris Parton Nov 28 '11 at 11:39
  • +1. It is really an interesting question; more than that the question is asked very nicely. A well-written question. – Nawaz Nov 30 '11 at 18:00
  • 1
    I came across an interesting example of this today: `auto_ptr p(new int); smart_map m; m[1]=p.release();` If you suppose that `smart_map::operator[]` might throw, you could have a case where the `auto_ptr` releases its ownership but the map never assumes the ownership, in the case where the RHS is evaluated before the LHS. (Suppose `smart_map` is like an STL `map`, except that it deletes the pointer value of each key/value pair on destruction.) – mrkj Jul 07 '12 at 05:10

4 Answers4

8

Order of evaluation would be unspecified in that case. Dont write such code

Similar example here

Community
  • 1
  • 1
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
7

The concept in C++ that governs whether the order of evaluation is defined is called the sequence point.

Basically, at a sequence point, it is guaranteed that all expressions prior to that point (with observable side effects) have been evaluated, and that no expressions beyond that point have been evaluated yet.

Though some might find it surprising, the assignment operator is not a sequence point. A full list of all sequence points is in the Wikipedia article.

Martin B
  • 23,670
  • 6
  • 53
  • 72
  • 2
    ... _was_ called the sequence point. Since this year, we're using _sequenced before_ / _sequenced after_. – MSalters Nov 28 '11 at 12:39
2

c++17 guarantees that bar() will be executed before foo().

Before c++17 this was unspecified behaviour and different compilers would evaluate in different orders. If both sides of the expression modify the same memory location then the behaviour is undefined.

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • *"undefined behaviour"*(UB) has special meaning. Here, (pre-c++17) order of evaluation was unspecified, but we don't have UB. – Jarod42 Oct 07 '22 at 12:07
  • @Jarod42 the order is unspecified (actually unsequenced) but the behaviour is undefined if there are side effects in unsequenced operations: https://en.cppreference.com/w/cpp/language/eval_order – Alan Birtles Oct 07 '22 at 12:32
  • We agree that `f() = f()++;` is UB. But function call introduces a sequence ("indeterminately sequenced" `11)` ), so , `f() = g();` would not be UB. – Jarod42 Oct 07 '22 at 13:25
0

Order of evaluation of an expression is Unspecified Behaviour.
It depends on the compiler which order it chooses to evaluate.

You should refrain from writing shuch codes.
Though if there is no side effect then the order shouldn't matter.

If the order matters, then your code is wrong/ Not portable/ may give different result accross different compilers**.

Praveen
  • 331
  • 2
  • 9