Which side of the assignment operator is evaluated first?
Asked Answered
M

4

13
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;
}
Mond answered 28/11, 2011 at 11:33 Comment(3)
+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 :)Oster
+1. It is really an interesting question; more than that the question is asked very nicely. A well-written question.Cursory
I came across an interesting example of this today: auto_ptr<int> p(new int); smart_map<int,int*> 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.)Haste
D
10

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

Similar example here

Diarrhoea answered 28/11, 2011 at 11:35 Comment(0)
S
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.

Sore answered 28/11, 2011 at 11:49 Comment(1)
... was called the sequence point. Since this year, we're using sequenced before / sequenced after.Soll
S
3

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.

Silma answered 7/10, 2022 at 11:28 Comment(3)
*"undefined behaviour"*(UB) has special meaning. Here, (pre-c++17) order of evaluation was unspecified, but we don't have UB.Mangrum
@Mangrum the order is unspecified (actually unsequenced) but the behaviour is undefined if there are side effects in unsequenced operations: en.cppreference.com/w/cpp/language/eval_orderSilma
We agree that f() = f()++; is UB. But function call introduces a sequence ("indeterminately sequenced" 11) ), so , f() = g(); would not be UB.Mangrum
L
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**.

Lateen answered 28/11, 2011 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.