Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Temporary object lifetime in expressions

298 views
Skip to first unread message

pota...@gmail.com

unread,
Mar 6, 2009, 3:21:43 AM3/6/09
to
Hello, all-knowing Everybody,

For all my self-conscious file I was sure that temporary object will
be destructed right after calculating expression that using this
object will be computed. However, the following example illustrates
that temporary objects lives a bit longer than expression:

class A
{
string s_;
public:
A(const string& s)
:s_(s)
{
cout<<"A::A(): "<<s_<<endl;
}
~A()
{
cout<<"~A::A(): "<<s_<<endl;
}
const char* operator()()const
{
cout<<"A::operator(): "<<s_<<endl;
return s_.c_str();
}
};
...
A( A("hello, world")()+7 );

In my assumptions this code should be incorrect and print something
like the following:
A::A(): hello, world
A::operator(): hello, world
~A::A(): hello, world
A::A(): world //here some error should occur or data should be
incorrect
~A::A(): world

But in fact I see that first object (with "hello, world") is being
destructed last:
A::A(): hello, world
A::operator(): hello, world
A::A(): world
~A::A(): world
~A::A(): hello, world

Can anybody explain (or quote appropriate standard paragraph) this
behaviour?

Thanks in advance,
Dmitry.
----
MERA NN,
Nizhny Novgorod, Russian Federation

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Zeppe

unread,
Mar 6, 2009, 11:23:51 PM3/6/09
to
pota...@gmail.com wrote [06/03/09 08:21]:
> Hello, all-knowing Everybody,

hello, even though I'm by far not one of them :)

>
> For all my self-conscious file I was sure that temporary object will
> be destructed right after calculating expression that using this
> object will be computed.

mostly right.

> However, the following example illustrates
> that temporary objects lives a bit longer than expression:

this doesn't seem really the case here...

[cut]


> A( A("hello, world")()+7 );

[cut]


>
> Can anybody explain (or quote appropriate standard paragraph) this
> behaviour?

two temporary are being instantiated here, an external one (the one
initialized with "world") and an internal one (initialised with "hello,
world"). The lifetime rules are:
a) the external object, being an unnamed object, is destroyed at the end
of the full expression (the quoted one);
b) the internal object, being a temporary bound to a reference that is
the argument of a function call, is destroyed also the end of the full
expression (§12.2.5)
c) as of the standard (§12.2.5), "...the destruction of temporaries
bound to references shall take into account the ordering of destruction
of objects with static or automatic storage duration (3.7.1, 3.7.2);
that is, [...] if obj2 is an object with static or automatic storage
duration created after the temporary is created, the temporary shall be
destroyed after obj2 is destroyed", which means, when destructing the
internal object, since the external one (obj2 in the standard wording)
has been created after the internal, it has to be destroyed after.

Best wishes,

Giuseppe

florin

unread,
Mar 6, 2009, 11:58:35 PM3/6/09
to
On Mar 6, 10:21 am, potapo...@gmail.com wrote:

>
> For all my self-conscious file I was sure that temporary object will
> be destructed right after calculating expression that using this
> object will be computed.

Hmm, not exactly.

To paraphrase Herb Sutter : "Normally, a temporary object lasts only
until the end of the full expression in which it appears. However, C++
deliberately specifies that binding a temporary object to a reference
to const on the stack lengthens the lifetime of the temporary to the
lifetime of the reference itself".

So, in your example:


A( A("hello, world")()+7 );

the temporary object is bind to const string& which is a const
reference (of course :) and that will extend the life of the
temporary.

Bo Persson

unread,
Mar 6, 2009, 11:59:11 PM3/6/09
to
pota...@gmail.com wrote:
> Hello, all-knowing Everybody,

>
> ...
> A( A("hello, world")()+7 );
>
> In my assumptions this code should be incorrect and print something
> like the following:
> A::A(): hello, world
> A::operator(): hello, world
> ~A::A(): hello, world
> A::A(): world //here some error should occur or data should be
> incorrect
> ~A::A(): world
>
> But in fact I see that first object (with "hello, world") is being
> destructed last:
> A::A(): hello, world
> A::operator(): hello, world
> A::A(): world
> ~A::A(): world
> ~A::A(): hello, world
>
> Can anybody explain (or quote appropriate standard paragraph) this
> behaviour?
>

The temporaries live till the end of the full expression. That's at
the semicolon, in your example.

I don't know if there is a required order for the destruction of
several temporaries here, but the reverse order of their construction
is what is required elsewhere.


Bo Persson

Pavel Minaev

unread,
Mar 7, 2009, 12:04:28 AM3/7/09
to

12.2[class.temporary]/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."

full-expression for your case is the whole statement up to the
semicolon, so the inner temporary is not destroyed until then.

As for the order of destruction, the rule is the same as usual -
objects are destructed in reverse order; whichever one was constructed
last will be destructed first.

Bart van Ingen Schenau

unread,
Mar 7, 2009, 1:04:46 AM3/7/09
to
pota...@gmail.com wrote:

> Hello, all-knowing Everybody,
>
> For all my self-conscious file I was sure that temporary object will
> be destructed right after calculating expression that using this
> object will be computed. However, the following example illustrates
> that temporary objects lives a bit longer than expression:

Yes, temporaries live till the end of the /full expression/ in which
they were created.
A /full expression/ is an expression that is not a part of a larger
expression.

The standards paragraph is 12.2 [class.temporary].
It states that both A objects will persist until the end of the
initialisation of the outer A, and that the two objects will be
destructed in reverse order of their construction.

{ edits: 7 lines quoted sig removed. do not quote extraneous material. -mod }

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

Pavel Minaev

unread,
Mar 8, 2009, 6:34:59 AM3/8/09
to
On Mar 6, 8:59 pm, "Bo Persson" <b...@gmb.dk> wrote:
> The temporaries live till the end of the full expression. That's at
> the semicolon, in your example.
>
> I don't know if there is a required order for the destruction of
> several temporaries here, but the reverse order of their construction
> is what is required elsewhere.

The standard seems to be somewhat murky in that regard. I don't see it
explicitly spelling out the order for non-bound temporaries, only for
bound ones. However, it does give an example listing in 12.2
[class.temporary]/5:

class C {
// ...
public:
C();
C(int);
friend C operator+(const C&, const C&);
˜C();
};
C obj1;
const C& cr = C(16)+C(23);
C obj2;

and then goes on to say:

the expression C(16)+C(23) creates three temporaries. A first
temporary T1 to hold the result of the
expression C(16), a second temporary T2 to hold the result of the
expression C(23), and a third temporary
T3 to hold the result of the addition of these two expressions. The
temporary T3 is then bound to the
reference cr. It is unspecified whether T1 or T2 is created first.
On an implementation where T1 is created
before T2, it is guaranteed that T2 is destroyed before T1.

which seems to imply that the order is guaranteed.

0 new messages