Reputation: 13
In a C++ Class, I 've overloaded operator-(). When I compile with -O0, it behaves as expected but when I compile with at least -O1, the result of calling operator-() is wrong despite no error is generated.
I'm not a C++ guru but nothing seems weird to me in the code snippet below. Unlike other cases I encountered on this site, I have no inline asm, I'm not calling a library, etc. Everything is self contained in the code.
Here are the version of gcc I used :
g++ (GCC) 4.9.3
Copyright © 2015 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.
Il n'y a PAS GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.
g++ (GCC) 5.2.0
Copyright © 2015 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.
Il n'y a PAS GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.
Compilation commands :
OK : g++ --std=c++11 -O0 -o test test.cpp
KO : g++ --std=c++11 -O1 -o test test.cpp
I get the expected warning :
test.cpp: In member function ‘A& A::operator-(const A&)’:
test.cpp:23:5: attention : reference to local variable ‘tmp’ returned
[-Wreturn-local-addr]
A tmp(*this);
^
Adding -Wno-return-local-addr changes nothing since it's just removing the warning
Here is the code snippet which reproduces the problem :
#include <iostream>
using namespace std;
class A {
public:
double val;
A(int _val) : val(_val) {}
A() : val(0.0) {}
A(const A&) = default;
A(A&&) = default;
A& operator=(const A&) = default;
A& operator=(A&&) = default;
A& operator-(const A& other) {
A tmp(*this);
tmp.val -= other.val;
return tmp;
}
};
int main() {
A a(3);
A b(2);
A c = b - a;
cout << c.val << endl;
return 0;
}
If I add an operator-=()
A& operator-=(const A& other) {
this->val -= other.val;
return *this;
}
and change in main :
A c = b - a;
with
A c(b);
c -= a;
I works perfectly whatever the -Ox option.
I suspect that returning a reference to a local variable from operator-() is the source of the problem (despite the RVO feature of c++11 ?). What I don't get is why the level of optimization has such an effect ?
After all, is there something wrong with mys code ?
Upvotes: 1
Views: 355
Reputation: 36597
Your operator-()
is returning a reference to a local variable. That causes the caller to exhibit undefined behaviour if it uses that reference.
Conventionally, operator-()
returns an object by value, not by reference. This makes sense, as c = a - b
typically leaves a
and b
unchanged, and gives c
the difference (however that is defined) between them.
Upvotes: 3