473,218 Members | 1,581 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,218 software developers and data experts.

Temporary Object Lifetime

Hello all,

class Foo {/* Details don't matter */};

class Bar {
public:
Bar(): m_Foo(/* Construct a Foo however it wants to be constructed
*/);
const Foo &GetFoo() const { return m_Foo; }
private:
Foo m_Foo;
};

int main() {
const Foo &OneFoo = Bar().GetFoo();
// Do stuff with OneFoo. Is this legal given the use of
// temporaries above?
}

Thanks,
Dave
Jun 27 '08 #1
6 2638
On Jun 12, 5:17 pm, "better_cs_...@yahoo.com"
<better_cs_...@yahoo.comwrote:
int main() {
const Foo &OneFoo = Bar().GetFoo();
// Do stuff with OneFoo. Is this legal given the use of
// temporaries above?
Not it is not.
Check this out and give your self an answer
#include <iostream>
#include <cstdlib>

class Foo {
public:
~Foo(){std::cerr << "die foo" << std::endl;}
};

class Bar {
public:
Bar(): m_Foo(){}
~Bar(){std::cerr << "die bar" << std::endl;}
const Foo &GetFoo() const { return m_Foo; }
private:
Foo m_Foo;

};

int main() {
const Foo &OneFoo = Bar().GetFoo();
std::cerr << "do stuff with OneFoo?" << std::endl;
}
Jun 27 '08 #2
be***********@yahoo.com wrote:
class Foo {/* Details don't matter */};

class Bar {
public:
Bar(): m_Foo(/* Construct a Foo however it wants to be constructed
*/);
const Foo &GetFoo() const { return m_Foo; }
private:
Foo m_Foo;
};

int main() {
const Foo &OneFoo = Bar().GetFoo();
// Do stuff with OneFoo. Is this legal given the use of
// temporaries above?
}
I don't believe so. The 'Bar' temporary is not bound to the reference,
so it's not going to live beyond 'OneFoo's initialisation.

Had 'Bar' derived from 'Foo' *and* you did

const Foo &OneFoo = Bar();

, then the 'Bar' would have a subobject of type 'Foo' that ought to
survive longer than the full expression, and as the superobject to the
temporary bound to a reference, the 'Bar' temporary would have to stay
alive as long as 'OneFoo'. But your case is not that. In your case you
create a reference to a data member (which does live even shorter than
the 'Bar' object that contains it), so as soon as the initialisation is
complete, the 'OneFoo' reference becomes *invalid*.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #3
On Jun 12, 10:17 pm, "better_cs_...@yahoo.com"
<better_cs_...@yahoo.comwrote:
class Foo {/* Details don't matter */};
class Bar {
public:
Bar(): m_Foo(/* Construct a Foo however it wants to be constructed
*/);
const Foo &GetFoo() const { return m_Foo; }
private:
Foo m_Foo;
};
int main() {
const Foo &OneFoo = Bar().GetFoo();
// Do stuff with OneFoo. Is this legal given the use of
// temporaries above?
}
No. The lifetime of the temporary is until the end of the full
expression. The lifetime of a temporary will be extended if it
is used to initialize a const reference, but that's not the case
anywhere in your code above. (The reference in the return value
is initialized with an lvalue, not a temporary, and the
reference in main is initialized with another reference.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #4
On Jun 12, 10:40 pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
better_cs_...@yahoo.com wrote:
class Foo {/* Details don't matter */};
class Bar {
public:
Bar(): m_Foo(/* Construct a Foo however it wants to be constructed
*/);
const Foo &GetFoo() const { return m_Foo; }
private:
Foo m_Foo;
};
int main() {
const Foo &OneFoo = Bar().GetFoo();
// Do stuff with OneFoo. Is this legal given the use of
// temporaries above?
}
I don't believe so. The 'Bar' temporary is not bound to the
reference, so it's not going to live beyond 'OneFoo's
initialisation.
That's irrelevant. The fact that a reference is bound to a
temporary has no effect on the lifetime of the temporary. The
only time the lifetime of the temporary is extended is when the
temporary is used to initialize the reference, and that's not
the case here: the reference in main is initialized with another
reference, and the reference returned by Bar::GetFoo() is
initialized by an lvalue, not a temporary (and reference return
values are a special case anyway, and don't extend the lifetime
of the temporary, even if they're initialized with one).
Had 'Bar' derived from 'Foo' *and* you did
const Foo &OneFoo = Bar();
, then the 'Bar' would have a subobject of type 'Foo' that ought to
survive longer than the full expression, and as the superobject to the
temporary bound to a reference, the 'Bar' temporary would have to stay
alive as long as 'OneFoo'.
But your case is not that. In your case you create a
reference to a data member (which does live even shorter than
the 'Bar' object that contains it), so as soon as the
initialisation is complete, the 'OneFoo' reference becomes
*invalid*.
The key isn't whether something is a subobject or not. In his
initial example, the reference is bound to a sub-object of the
temporary as well. The key here is that the temporary is
initializing the reference directly; if m_Foo were public and
you wrote:

Foo const& &OneFoo = Bar().m_Foo ;

it would be fine as well. It's the indirections in his case
which break the code.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #5
Hi,
That's irrelevant. The fact that a reference is bound to a
temporary has no effect on the lifetime of the temporary. The
only time the lifetime of the temporary is extended is when the
temporary is used to initialize the reference,
Is it a compiler deficiency or regular standard complience if
additional copy constructor is called during such an initialization?

Slightly modified sample with string member and a pointer:

===code tmptst1.cpp ===

#include <iostream>
#include <cstdlib>
#include <string>

class Foo {
public:
Foo( const std::string& str ) : msg(str), p(0)
{std::cerr << "up foo" << std::endl;
p = new char[10];}
Foo( const Foo& src ) : msg( "bad foo" ), p(0)
{std::cerr << "copy foo" << std::endl;
p = new char[20];}
~Foo()
{std::cerr << "die foo" << std::endl;
delete[] p;}
void doSomeThing() const { std::cout << msg << std::endl; }
private:
std::string msg;
char* p;

};
class Bar {
public:
Bar( const std::string& str ): m_Foo( str )
{std::cerr << "up bar" << std::endl;}
~Bar(){std::cerr << "die bar" << std::endl;}
const Foo &GetFoo() const { return m_Foo; }

Foo m_Foo;
};
int main() {
// const Foo &OneFoo = Bar( "Hi there!" ).GetFoo();
const Foo &OneFoo = Bar( "Hi there!" ).m_Foo;
std::cerr << "do stuff with OneFoo?" << std::endl;
OneFoo.doSomeThing();

}
===code tmptst1.cpp ===
produces this output if compiled with MSVC.NET 2008

cl /EHsc /O2 /NDEBUG tmptst1.cpp

up foo
up bar
copy foo
die bar
die foo
do stuff with OneFoo?
bad foo
die foo
Jun 27 '08 #6
On Jun 13, 12:34 pm, Ucayaly Fish <UcayalyF...@gmail.comwrote:
That's irrelevant. The fact that a reference is bound to a
temporary has no effect on the lifetime of the temporary. The
only time the lifetime of the temporary is extended is when the
temporary is used to initialize the reference,
Is it a compiler deficiency or regular standard complience if
additional copy constructor is called during such an initialization?
Yes:-).

Seriously, it depends on what version of the standard you're
looking at. All of the currently approved versions *require* a
copy (and then authorize it to be optimized away).
Slightly modified sample with string member and a pointer:
===code tmptst1.cpp ===

#include <iostream>
#include <cstdlib>
#include <string>

class Foo {
public:
Foo( const std::string& str ) : msg(str), p(0)
{std::cerr << "up foo" << std::endl;
p = new char[10];}
Foo( const Foo& src ) : msg( "bad foo" ), p(0)
{std::cerr << "copy foo" << std::endl;
p = new char[20];}
~Foo()
{std::cerr << "die foo" << std::endl;
delete[] p;}
void doSomeThing() const { std::cout << msg << std::endl; }
private:
std::string msg;
char* p;
};

class Bar {
public:
Bar( const std::string& str ): m_Foo( str )
{std::cerr << "up bar" << std::endl;}
~Bar(){std::cerr << "die bar" << std::endl;}
const Foo &GetFoo() const { return m_Foo; }
Foo m_Foo;
};

int main() {
// const Foo &OneFoo = Bar( "Hi there!" ).GetFoo();
const Foo &OneFoo = Bar( "Hi there!" ).m_Foo;
std::cerr << "do stuff with OneFoo?" << std::endl;
OneFoo.doSomeThing();
}
The standard isn't really very clear here. My interpretation
was that it more or less required the Bar object to be
destructed at the end of the full expression, while requiring
that the Foo object have its lifetime extended (and that this
was the motivation behind "allowing" the copy). This section
has been reworked some in the current draft, and FROM MEMORY, I
think the draft forbids the copy, and requires extension of the
Bar object's (the containing object's) lifetime. We're in the
middle of moving here, however, and my copies of the various
versions of the standard are on a network which is not reachable
for the moment, so I can't verify this one way or the other.
===code tmptst1.cpp ===
produces this output if compiled with MSVC.NET 2008
cl /EHsc /O2 /NDEBUG tmptst1.cpp
up foo
up bar
copy foo
die bar
die foo
do stuff with OneFoo?
bad foo
die foo
It's definitely conform with C++03, and from memory, it's also
what g++ does (but since NIS isn't working, I can only access
local disks on my Unix machines, so I can't try anything).

Arguably, the compiler is required to call Bar's destructor at
the end of the full expression, and if it does, the only way to
extend the lifetime of the temporary is to make a copy.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
Jun 27 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: White Wolf | last post by:
Hi, I would like to double check how long a temporary returned by a function lives? Suppose I have an instance of a class type C, which has a member function returning some sort of...
8
by: pt | last post by:
Hallo, i wonder how it is going to be of this code below regarding of the return of temporary object. Prototypes: =========== bool Activation(TCHAR *c); std::basic_string<TCHAR> GetFile();
6
by: Jonathan Turkanis | last post by:
Dear All, I'm using VC7.1. The test program at the end of this message initializes a member variable of reference type with a temporary. I believe the program should output counter = 0;...
1
by: Alexander Stippler | last post by:
Here my code snippet: //---------------------- struct Thing { }; template <typename T> struct Wrap
4
by: Jess | last post by:
Hello, If a function's signature is: T f(); and it returns its result (of type T) by value, then the result will be copied into a temporary place, as a temporary object. If it is a...
10
by: Jess | last post by:
Hello, If I create a temporary object using a dynamically created object's pointer, then when the temporary object is destroyed, will the dynamically created object be destroyed too? My guess...
5
by: Juha Nieminen | last post by:
Let's assume we have a class like this: //--------------------------------------------------------- #include <iostream> class MyClass { public: MyClass() { std::cout << "constructor\n"; }...
2
by: casul | last post by:
Hi All, Given the following code : char const & identity( char const &c ) { return c; } char const & f( ) { return identity('A'); } char const & g( ) { return 'A'; } Of course, the...
5
by: coolguyaroundyou | last post by:
Consider the following codes: class abc { int i; public: abc() : i(0) {} void func() { .....some code....} };
1
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: mar23 | last post by:
Here's the situation. I have a form called frmDiceInventory with subform called subfrmDice. The subform's control source is linked to a query called qryDiceInventory. I've been trying to pick up the...
2
by: jimatqsi | last post by:
The boss wants the word "CONFIDENTIAL" overlaying certain reports. He wants it large, slanted across the page, on every page, very light gray, outlined letters, not block letters. I thought Word Art...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.