views:

269

answers:

4

The following code prints one,two,three. Is that desired and true for all C++ compilers?


class Foo
{
      const char* m_name;
public:
      Foo(const char* name) : m_name(name) {}
      ~Foo() { printf("%s\n", m_name); }
};

void main()
{
      Foo foo("three");
      Foo("one");   // un-named object
      printf("two\n");
}
+4  A: 

The scope of a temporary object like that is just one line. Think about it, you can no longer reference it after the line ends, so why would the object remain around?

If this weren't the case, compilers wouldn't be able to optimize out temporary objects in function calls.

JonM
+17  A: 

A temporary variable lives until the end of the full expression it was created in. Yours ends at the semicolon.

This is in 12.2/3:

Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created.

Your behavior is guaranteed.

There are two conditions that, if met, will extend the lifetime of a temporary. The first is when it's an initializer for an object. The second is when a reference binds to a temporary.

GMan
... uless the conditions from 12.2/4 are met, which can extend the lifetime of a temporary even further.
AndreyT
@AndreyT: Er, yes. I suppose that may be important to mention.
GMan
@GMan: It might not be important to mention in the context of the original question. But after reading your explicit assertion that says "lifetime of a temporary variable is up when the expression ends" I thought that it is something worth mentioning.
AndreyT
@Andrey: I agree, my original post made it seem unconditional.
GMan
+3  A: 

Yes, it is desired.

Foo foo("three") creates a normal object which will be destroyed when the scope ends.

Foo("one") creates a temporary object, which is destroyed at the end of the instruction[1]. Why? Because you there is no way you can access it after the instruction has ended.

[1] Deliberate semplification: I should have said sequence point.

Danilo Piazzalunga
Sequence point has nothing to do with this. The lifetime of the temporary ends at the end of the full expression, even if there is a sequence point at the end of the "instruction" that created the object. For example, in `Foo("a"), Foo("b"), Foo("c");` all three temporaries are guaranteed to live to the end of the statement, even though there are sequence points in the middle.
AndreyT
+5  A: 

The rules that govern the lifetimes of temporary objects have nothing to do with notion of scope. Scope is a property of a name, and temporary objects do not have names. In other words, temporary objects have no scope.

Most of the time the lifetime of a temporary object ends at the end of the full expression that created that object, which is what you observed in your experiment. This is the general rule that has some exceptions. The main one is that if you immediately attach a reference to your temporary object, the lifetime of the object will be extended to match the lifetime of the reference

const Foo &rfoo = Foo("one");

The above temporary will live as long as rfoo lives.

AndreyT