Topic: Question related to destruction of temporaries
Author: johnchx2@yahoo.com (johnchx)
Date: Wed, 6 Oct 2004 03:48:49 GMT Raw View
nagle@animats.com (John Nagle) wrote
> Andrei Alexandrescu (See Website for Email) wrote:
> > Given a structure
> >
> > struct X { ... };
> >
> > and a function
> >
> > X& Foo(X val) {
> > return val;
> > }
> >
> > is Foo legal, assuming that no caller of Foo will save the returned
> > reference beyond the full-expression that calls Foo?
>
> No.
>
> That's definitely wrong. That's a simple reference
> to a temporary already out of scope.
Just a nit: if the call of Foo() actually does denote a temporary,
then, since the temporary is guaranteed to survive to the end of the
full expression, it is safe to use until that point. The problem
arises if it turns out that the call of Foo() denotes an object which
is *not* a temporary, but which is simply and solely the function
parameter. In that case, the object is destroyed on return from the
function and making use of it UB.
If the object designated by the function call is "both" a parameter
and a temporary, then the longer lifetime applies (12.8/15).
Of course, the conclusion -- "Don't do that!" -- remains the same.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See Website for Email)")
Date: Mon, 4 Oct 2004 00:25:49 GMT Raw View
I remember having recently skimmed a short paper on destruction of
temporaries. I vaguely recall the author was one of the EDG (Adamczyk
maybe?) and it addressed the following issue: when are the temporaries
constructed as function arguments destroyed: at the end of the function
call, or at the end of the full expression containing the function call?
I was in a haste while reading that paper, so the conclusion didn't stick
with me and I can't find it again. Could someone point it out to me?
I recall there is some ambiguity with regard to the issue. So let me ask a
related question.
Given a structure
struct X { ... };
and a function
X& Foo(X val) {
return val;
}
is Foo legal, assuming that no caller of Foo will save the returned
reference beyond the full-expression that calls Foo?
Andrei
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Mon, 4 Oct 2004 15:15:09 GMT Raw View
Andrei Alexandrescu (See Website for Email) wrote:
> I remember having recently skimmed a short paper on destruction of
> temporaries. I vaguely recall the author was one of the EDG (Adamczyk
> maybe?) and it addressed the following issue: when are the temporaries
> constructed as function arguments destroyed: at the end of the function
> call, or at the end of the full expression containing the function call?
>
> I was in a haste while reading that paper, so the conclusion didn't stick
> with me and I can't find it again. Could someone point it out to me?
>
> I recall there is some ambiguity with regard to the issue. So let me ask a
> related question.
>
> Given a structure
>
> struct X { ... };
>
> and a function
>
> X& Foo(X val) {
> return val;
> }
>
> is Foo legal, assuming that no caller of Foo will save the returned
> reference beyond the full-expression that calls Foo?
No.
That's definitely wrong. That's a simple reference
to a temporary already out of scope. (Think about the
implementation problem. If Foo is separately
compiled, and the implementation uses an ordinary stack
for temporaries, all of Foo's storage is gone when Foo
returns.)
One might argue over
struct X { ...
X(int n); // constructor
};
X& Foo(X& val) {
return val;
}
X a = Foo(X(1));
where X(1) is constructing an X, which is passed
in and then passed back out by reference. It's not clear
how long the temporary object survives. This can
be implemented in ways so that this works, and in ways
so that it doesn't.
John Nagle
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: tom_usenet@hotmail.com (Tom Widmer)
Date: Mon, 4 Oct 2004 15:15:22 GMT Raw View
On Mon, 4 Oct 2004 00:25:49 GMT,
SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See
Website for Email)") wrote:
>I remember having recently skimmed a short paper on destruction of
>temporaries. I vaguely recall the author was one of the EDG (Adamczyk
>maybe?) and it addressed the following issue: when are the temporaries
>constructed as function arguments destroyed: at the end of the function
>call, or at the end of the full expression containing the function call?
They aren't temporaries; "val" below is a variable in the scope of
Foo, not a temporary in the scope of the caller.
>I was in a haste while reading that paper, so the conclusion didn't stick
>with me and I can't find it again. Could someone point it out to me?
>
>I recall there is some ambiguity with regard to the issue. So let me ask a
>related question.
>
>Given a structure
>
>struct X { ... };
>
>and a function
>
>X& Foo(X val) {
> return val;
>}
>
>is Foo legal, assuming that no caller of Foo will save the returned
>reference beyond the full-expression that calls Foo?
No, I don't think it's legal. "val" is destroyed right after binding
it to the returned reference, when the Foo scope is exited. Except you
might of course get lucky if val was initialized from a temporary
(since the temporary will last until the end of the full expression at
the call site, and the copy may have been elided, and hence won't be
destroyed at the "return"), but since temporary elision is entirely
compiler dependent, this is relying on unspecified behaviour.
But I may be wrong...
Tom
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Mon, 4 Oct 2004 15:16:31 GMT Raw View
Andrei Alexandrescu (See Website for Email) wrote:
> I remember having recently skimmed a short paper on destruction of
> temporaries. I vaguely recall the author was one of the EDG (Adamczyk
> maybe?) and it addressed the following issue: when are the temporaries
> constructed as function arguments destroyed: at the end of the function
> call, or at the end of the full expression containing the function call?
>
> I was in a haste while reading that paper, so the conclusion didn't stick
> with me and I can't find it again. Could someone point it out to me?
>
> I recall there is some ambiguity with regard to the issue. So let me ask a
> related question.
>
> Given a structure
>
> struct X { ... };
>
> and a function
>
> X& Foo(X val) {
> return val;
> }
>
> is Foo legal, assuming that no caller of Foo will save the returned
> reference beyond the full-expression that calls Foo?
Aren't you binding a non-const reference to a temporary here?
V
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Mon, 4 Oct 2004 17:49:26 GMT Raw View
On Mon, 4 Oct 2004 00:25:49 GMT,
SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See
Website for Email)") wrote:
>I remember having recently skimmed a short paper on destruction of
>temporaries. I vaguely recall the author was one of the EDG (Adamczyk
>maybe?) and it addressed the following issue: when are the temporaries
>constructed as function arguments destroyed: at the end of the function
>call, or at the end of the full expression containing the function call?
>
>I was in a haste while reading that paper, so the conclusion didn't stick
>with me and I can't find it again. Could someone point it out to me?
>
>I recall there is some ambiguity with regard to the issue. So let me ask a
>related question.
>
>Given a structure
>
>struct X { ... };
>
>and a function
>
>X& Foo(X val) {
> return val;
>}
>
>is Foo legal, assuming that no caller of Foo will save the returned
>reference beyond the full-expression that calls Foo?
>
>
>Andrei
I found this ... hope it helps:
http://open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#201
--
Bob Hairgrove
NoSpamPlease@Home.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rtw@freenet.co.uk (Rob Williscroft)
Date: Mon, 4 Oct 2004 17:49:45 GMT Raw View
See Website for Email)" wrote in news:2sbeqnF1di98qU1@uni-berlin.de in
comp.std.c++:
> I remember having recently skimmed a short paper on destruction of
> temporaries. I vaguely recall the author was one of the EDG (Adamczyk
> maybe?) and it addressed the following issue: when are the temporaries
> constructed as function arguments destroyed: at the end of the
> function call, or at the end of the full expression containing the
> function call?
>
> I was in a haste while reading that paper, so the conclusion didn't
> stick with me and I can't find it again. Could someone point it out to
> me?
>
http://www.codesourcery.com/cxx-abi/argument-destruction.pdf
> I recall there is some ambiguity with regard to the issue. So let me
> ask a related question.
>
> Given a structure
>
> struct X { ... };
>
> and a function
>
> X& Foo(X val) {
> return val;
> }
>
> is Foo legal, assuming that no caller of Foo will save the returned
> reference beyond the full-expression that calls Foo?
>
No, its explaned in the pdf, but basicly iff the paramiter is copy
constructed from a temporary and the copy construction is elided then
the temporary becomes the paramiter, but its still a temporary so
the paramiter-temporary is destroyed at the end of the full expression
not after the return of the function.
But you can't rely on copy elision so its still UB.
Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See Website for Email)")
Date: Mon, 4 Oct 2004 17:49:52 GMT Raw View
"Tom Widmer" <tom_usenet@hotmail.com> wrote in message
news:nv72m0ttl9ug80cpimph2lps8885b6h2e0@4ax.com...
> On Mon, 4 Oct 2004 00:25:49 GMT,
> SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See
> Website for Email)") wrote:
>
>>I remember having recently skimmed a short paper on destruction of
>>temporaries. I vaguely recall the author was one of the EDG (Adamczyk
>>maybe?) and it addressed the following issue: when are the temporaries
>>constructed as function arguments destroyed: at the end of the function
>>call, or at the end of the full expression containing the function call?
>
> They aren't temporaries; "val" below is a variable in the scope of
> Foo, not a temporary in the scope of the caller.
It turns out the standard says that the temporary is created in the scope of
the caller. In particular, accessiblilty, lookup and all that are done
within the context of the caller.
Andrei
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See Website for Email)")
Date: Mon, 4 Oct 2004 17:59:29 GMT Raw View
"Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
news:3nd8d.3939$Ae.2409@newsread1.dllstx09.us.to.verio.net...
> Aren't you binding a non-const reference to a temporary here?
No, because within Foo, the object is not a temporary.
Andrei
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See Website for Email)")
Date: Mon, 4 Oct 2004 17:59:55 GMT Raw View
"John Nagle" <nagle@animats.com> wrote in message
news:JZ28d.23805$QJ3.8354@newssvr21.news.prodigy.com...
> Andrei Alexandrescu (See Website for Email) wrote:
>> is Foo legal, assuming that no caller of Foo will save the returned
>> reference beyond the full-expression that calls Foo?
>
> No.
>
> That's definitely wrong. That's a simple reference
> to a temporary already out of scope. (Think about the
> implementation problem. If Foo is separately
> compiled, and the implementation uses an ordinary stack
> for temporaries, all of Foo's storage is gone when Foo
> returns.)
An equivalent argument:
That's definitely correct. That's a simple reference to a temporary created
outside the call to Foo. (Think about the implementation problem. If Foo is
separately compiled, and the implementation uses an ordinary stack for
temporaries on which it puts the temporary before calling Foo, all of Foo's
storage is gone, but the temporary storage is still there when Foo returns,
and will last throgh the end of the full-expression calling Foo.)
Of course, none of the two arguments have value unless validated by the
standard. IIRC from the paper I mentioned, the standard strongly suggest my
semantics and disallows John's semantics.
> One might argue over
>
> struct X { ...
> X(int n); // constructor
> };
>
> X& Foo(X& val) {
> return val;
> }
>
> X a = Foo(X(1));
>
> where X(1) is constructing an X, which is passed
> in and then passed back out by reference. It's not clear
> how long the temporary object survives. This can
> be implemented in ways so that this works, and in ways
> so that it doesn't.
Exactly. Hence my question on what the standard has to say about it.
Andrei
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: mvorbrodt@poczta.onet.pl ("Martin Vorbrodt")
Date: Tue, 5 Oct 2004 15:27:03 GMT Raw View
Would this be a good testcase:
#include <iostream>
using namespace std;
class Test {
public:
Test() { cout << "+Test" << endl; }
Test(const Test& t) { cout << "+TestC" << endl; }
~Test() { cout << "-Test" << endl; }
void mf() {
cout << "foo" << endl;
}
};
Test& Foo(Test t) {
return t;
}
void Bar(Test& t) {
t.mf();
}
int main() {
Test t;
Bar(Foo(t));
}
This prints out:
+Test
+TestC
foo
-Test
-Test
Which implies that the reference to temporary still exists after Foo returns
and execution enters Bar. So to answer your question, I believe the
remporeries exist until the end of the expression in which the function
exists.
Martin.
P.S. "Modern C++ Design..." Great Book!
""Andrei Alexandrescu (See Website for Email)""
<SeeWebsiteForEmail@moderncppdesign.com> wrote in message
news:2sbeqnF1di98qU1@uni-berlin.de...
> I remember having recently skimmed a short paper on destruction of
> temporaries. I vaguely recall the author was one of the EDG (Adamczyk
> maybe?) and it addressed the following issue: when are the temporaries
> constructed as function arguments destroyed: at the end of the function
> call, or at the end of the full expression containing the function call?
>
> I was in a haste while reading that paper, so the conclusion didn't stick
> with me and I can't find it again. Could someone point it out to me?
>
> I recall there is some ambiguity with regard to the issue. So let me ask a
> related question.
>
> Given a structure
>
> struct X { ... };
>
> and a function
>
> X& Foo(X val) {
> return val;
> }
>
> is Foo legal, assuming that no caller of Foo will save the returned
> reference beyond the full-expression that calls Foo?
>
>
> Andrei
>
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alfps@start.no (Alf P. Steinbach)
Date: Tue, 5 Oct 2004 16:34:29 GMT Raw View
* "Andrei Alexandrescu (See Website for Email)":
>
> Given a structure
>
> struct X { ... };
>
> and a function
>
> X& Foo(X val) {
> return val;
> }
>
> is Foo legal, assuming that no caller of Foo will save the returned
> reference beyond the full-expression that calls Foo?
Nope. As Rob Williscroft has already replied. But more detailed
explanation: 'val' is only valid until 'Foo' returns -- and to
add some practice to this, if it's small enough then a reasonable
implementation may have passed the whole shebang on a call stack
where the stack unwinding will take care of wreaking as much havoc
as desired...
Yes, the compiler may choose to optimize things by eliding copy
construction, either by inlining a call of Foo or by creating a
version equivalent to pass-by-ref-to-const, in which case the result
would be in-practice valid also at a point after the function return.
No, you cannot rely on that.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Tue, 5 Oct 2004 17:26:02 GMT Raw View
Andrei Alexandrescu (See Website for Email) wrote:
>
> Exactly. Hence my question on what the standard has to say about it.
>
12.2/5 states that "[...] A temporary bound to the returned value in a
function return statement (6.6.3) persists until the function exits.
[...]" Is that of any relevance here?
Alberto
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]