I wrote this code that looked very simple to me at a first glance. It modifies a variable that is referenced by a reference variable and then returns the value of the reference. A simplified version that reproduces the odd behavior looks like this:
#include <iostream>
using std::cout;
struct A {
int a;
int& b;
A(int x) : a(x), b(a) {}
A(const A& other) : a(other.a), b(a) {}
A() : a(0), b(a) {}
};
int foo(A a) {
a.a *= a.b;
return a.b;
}
int main() {
A a(3);
cout << foo(a) << '\n';
return 0;
}
However, when it is compiled with optimization enabled (g++ 7.5), it produces output different to non-optimized code (i.e. 9 without optimizations - as expected, and 3 with optimizations enabled).
I am aware of the volatile
keyword, which prevents the compiler from reordering and other optimizations in the presence of certain side-effects (e.g. async execution and hardware-specific stuff), and it helps in this case as well.
However, I do not understand why I need to declare reference b as volatile in this particular case? Where is the source of error in this code?