C++ temporary variable lifetime
Asked Answered
F

3

5

Is this code valid?

int foo()
{
    std::vector<std::string>& v = std::vector<std::string>(5, "X");

    // Do something silly...

    return 42;
}

For some reason I thought that the temporary std::vector object (right from the assignment sign) should be destructed right after it's construction (thus rendering the reference invalid).

However, debugging proves that I'm wrong and, well, I realized that I don't quite understand why does the temporary variable is destructed when the function returns.


I guess I have a strong misunderstanding of something fundamental, so please enlighten me :)

Funchal answered 10/5, 2012 at 18:32 Comment(1)
When you say "debugging proves that I'm wrong", what exactly do you mean?Manifold
P
8

The code you've shown is illegal – temporaries can only bind to rvalue references or const lvalue references.

VC++ happens to allow it as an extension (and gives a level 4 warning saying so).

Philadelphia answered 10/5, 2012 at 18:34 Comment(6)
gcc complains nicely about this: error: invalid initialization of non-const reference of type 'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&' from a temporary of type 'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >Darrel
Thank you, didn't know about that extension (and, well, should've tried gcc).Funchal
@Yippie-Kai-Yay : Then you should be building with level 4 warnings enabled. ;-]Philadelphia
Note that if it would have been a const reference, it is legal. For a const reference, the life time of the temporary is extended to the life time of the const reference, which happens to be the end of the function.Arillode
@Philadelphia Probably I should :) However, what's the fundamental reason to implement some features against the standard and call them extensions? Legacy code problems?Funchal
@Yippie-Kai-Yay : In this case, yes, exactly – VC++'s own frameworks (MFC/ATL) abuse this extension. Note that the C++ standard specifically allows language extensions that enable otherwise ill-formed code to compile, as long as the compiler issues a diagnostic (warning in this case). You just didn't see the diagnostic because the default warning level is 3. :-]Philadelphia
T
3

The normal lifetime of a temporary is until the end of the full expression in which it is created; it's not necessarily destructed immediately on use. If the temporary is used to initialize a reference, it's lifetime is extended to match that of the reference (with the notable exception of a temporary created in the initializer list of a constructor).

Of course, your code is illegal; if the reference is to a non-const, it can only be initialized with some sort of an lvalue. But if it were legal (and at least one compiler accepts it), the lifetime should be extended to match that of the reference.

Toreutics answered 10/5, 2012 at 18:56 Comment(0)
M
2

You have a reference to a deallocated object. It works by 'sheer luck' (see The C++ Programming Language, section 10.4.10 Temporary Objects). You can't guarantee that it'll work in every compiler.

You can only be certain that the lifetime of the temporary is extended if it's bound to a const reference.

Microampere answered 10/5, 2012 at 18:42 Comment(4)
It's not sheer luck in this case, it's a language extension provided by the compiler the OP is using.Philadelphia
@Philadelphia I'm just quoting Stroustrup tongue-in-cheek. The point is that it's non-portable / illegal / unreliable or whatever you want to call it.Microampere
It's not portable, agreed, but it's also not illegal; the C++ standard (§1.4/8) specifically allows language extensions as long as the extension does not affect the behavior of well-formed code, and the compiler issues a diagnostic (warnings count).Philadelphia
Note that when the standard discusses the lifetime of temporaries, it speaks of extending the lifetime of temporaries bound to a reference. It doesn't say anything about const or not there. So logically, if the compiler accepts the initialization of a non-const reference with a temporary, it will also extend the lifetime of the temporary.Toreutics

© 2022 - 2025 — McMap. All rights reserved.