Re: reference lifetimes...
James Kanze wrote:
On Nov 11, 1:26 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
James wrote:
Here is my code:
#include <iostream>
struct foo
{
foo()
{
std::cout << this
<< "->foo::foo()"
<< std::endl;
}
~foo()
{
std::cout << this
<< "->foo::~foo()"
<< std::endl;
}
};
struct foo_holder
{
foo const& m_ref;
};
int main()
{
{
foo_holder fh = { foo() };
std::cout << "okay" << std::endl;
}
std::cout << std::endl;
{
foo const& ref = foo();
std::cout << "okay" << std::endl;
}
return 0;
}
Why does the const reference not properly maintain its
lifetime over the call to 'cout' when the reference is
contained within a POD 'foo_holder'? I get the following
output:
0x22ff50->foo::foo()
0x22ff50->foo::~foo()
okay
0x22ff50->foo::foo()
okay
0x22ff50->foo::~foo()
Something seems terribly wrong here... Is there anyway to
overcome this?
The form
T t = { blah };
is copy-initialisation.
But not of T. In his case, he copy initializes the member m_ref
of foo_holder with a temporary.
I think you're contradicting yourself here. If 'T' is an aggregate, and
the form
T t = { <initialiser list> };
does not perform copy-initialisation (from some temporary aggregate into
the 't' object), then there is no copy-initialisation of member 'm_ref'
anywhere, it's direct initialisation of the reference with a temporary,
which we know as "binding to a temporary".
The compiler is free to create another temporary (of your
class 'foo_holder') before initializing 'fh' with it, which
makes the temporary's 'm_ref' member bound to the temporary
'foo'.
I don't see anything in the standard which says that. He's
using aggregate initialization, which means that he's providing
a list of expressions to initialize each of the elements of the
aggregate. In his case, foo() is the expression which
initializes the foo_holder::m_ref, and not the foo_holder
itself. And the distinction between copy initialization and
direct initialization doesn't apply to either references or
aggregate initialization. (If you'll look at the points in
?8.5/14, you'll see that the standard sends you to another
section for both aggregate initialization and reference
initialization, before considering whether it is copy
initialization or not.) The compiler can still make a copy (at
least at present), but then it is the copy which is bound to the
reference, and whose lifetime is extended. (And of course, if
the compiler did make a copy, we'd see two calls to the
destructor each time.)
Not a copy of 'foo', a copy of 'foo_holder', which has no destructor,
but it's irrelevant. It's possible that GC++ creators followed the same
faulty logic I did, and came to the conclusion that they need to create
a temporary of type 'foo_holder', which then allowed destruction of the
temporary 'foo'.
The 'foo_holder' temporary is destroyed after initialising of
the 'fh' variable, causing the destruction of your foo'
temporary.
There is no foo_holder temporary.
Well, how do you know that the compiler doesn't create it? Unless the
OP looks at the generated assembly code, there is no way to tell, is
there? I mean, in real life. Perhaps you're saying that the Standard
requires that there shan't be any copies of 'foo_holder' objects created
during initialisation (brace-enclosed), IOW copying is prohibited. Then
you're right and the GC++ has a bug.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask