While porting some C++ code from Microsoft Visual Studio to gcc, I ran into a weird bug, which I eventually boiled down to this:
#include <iostream>
using namespace std;
class Foo {
public:
int data;
Foo(int i) : data(i)
{
cout << "Foo constructed with " << i << endl;
}
Foo(const Foo& f) : data(f.data)
{
cout << "copy ctor " << endl;
}
Foo(const Foo&& f) : data(f.data)
{
cout << "move ctor" << endl;
}
~Foo()
{
cout << "Foo destructed with " << data << endl;
}
};
int Bar(Foo f)
{
cout << "f.data = " << f.data << endl;
return f.data * 2;
}
int main()
{
Foo f1(10);
Foo f2(Bar(std::move(f1)));
}
If I compile and run the above code with Microsoft Visual Studio 2015 Community, I get the following output:
Foo constructed with 10
move ctor
f.data = 10
Foo destructed with 10
Foo constructed with 20
Foo destructed with 20
Foo destructed with 10
However, if I compile and run the code with gcc 6.1.1 and --std=c++14, I get this output:
Foo constructed with 10
move ctor
f.data = 10
Foo constructed with 20
Foo destructed with 10
Foo destructed with 20
Foo destructed with 10
gcc calls the destructor of f, the argument to Bar(), after Bar() returns, while msvc calls the destructor (apparently) before it returns, or at least before the constructor of f2. When is f supposed to be destructed, according to the C++ standard?