I have a TestClass
with a const&
member variable. I know from various places and own experiences that it is a bad idea to initialize this const&
with the reference to a temporary value. So I was quite suprised that the following code will compile fine (tested with gcc-4.9.1
, clang-3.5
, and scan-build-3.5
) but fail to run properly.
class TestClass {
public:
// removing the "reference" would remove the temporary-problem
const std::string &d;
TestClass(const std::string &d)
: d(d) {
// "d" is a const-ref, cannot be changed at all... if it is assigned some
// temporary value it is mangled up...
}
};
int main() {
// NOTE: the variable "d" is a
// temporary, whose reference is not valid... what I don't get in the
// moment: why does no compiler warn me?
TestClass dut("d");
// and printing what we got:
std::cout << "beginning output:\n\n";
// this will silently abort the program (gcc-4.9.1) or be empty
// (clang-3.5) -- don't know whats going on here...
std::cout << "dut.d: '" << dut.d << "'\n";
std::cout << "\nthats it!\n";
return 0;
}
Why does none of the two compilers warn me at compile-time? See also this ideone, with some more testing going on.
No warning as no offense:
local
const
references prolong the lifespan of the variable.The standard specifies such behavior in §8.5.3/5, [dcl.init.ref], the section on initializers of reference declarations. The lifetime extension is not transitive through a function argument. §12.2/5 [class.temporary]:
You can have a look at gotw-88 for an extended and more readable discussion on this topic.
Undefined Behaviour
So is it your code correct? Nope, and its execution will lead to undefined behaviour. The real problem in your code snapshot is that the Undefined Behaviour is caused by the mix of two perfectly legal operations: the call of the constructor passing a temporary object (whose life spans inside the constructor block) and the binding of the reference in the constructor definition.
The compiler is not smart enough to detect this explosive statement combination, so this is why you don't get any warning.