C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Lifetime extension misconception

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
Frederick Gotham
Guest





PostPosted: Sun Jul 30, 2006 1:34 am    Post subject: Lifetime extension misconception Reply with quote



There is a common misconception, (one which I myself also held at one point),
that a const reference can "extend the lifetime of a temporary". Examples
such as the following are given:

Snippet (1)
-----------

#include <string>
using std::string;

#include <iostream>
using std::cout;

string Func()
{
return "Hello";
}

int main()
{
string const &str = Func();

cout << str << '\n';
}

In the above snippet, no temporary "has had its lifetime extended". If such a
thing were true, then the following code would be perfectly OK:

Snippet (2):
------------

#include <string>
using std::string;

string Func()
{
return "Hello";
}

int main()
{
string const &cstr = Func();

string &str = const_cast<string&>(cstr);

str = "World";
}


But alas, Snippet (2) exhibits undefined behaviour, because the reference
does not refer to the original non-const object which was returned by value
from the function.

The code in Snippet (1) works on exactly the same principle as the following
code snippet:

Snippet (3):
------------

int main()
{
int const &r = 5;
}

In Snippet (1) and in Snippet (3), the const reference remains valid NOT
because a temporary has had its liftime extended, but because the reference
was initialised with an R-value. The C++ Standard defines this process:

If the initializer expression is an rvalue, with T2 a class type, and “cv1
T1” is reference-compatible with “cv2 T2,” the reference is bound in one of
the following ways (the choice is implementation-defined):
— The reference is bound to the object represented by the rvalue (see 3.10)
or to a sub-object within that object.
— A temporary of type “cv1 T2” [sic] is created, and a constructor is called
to copy the entire rvalue object into the temporary. The reference is bound
to the temporary or to a sub-object within the temporary.

This explains why the following code snippet fails to compile, and disproves
that the lifetime of a temporary is extended by binding a const reference to
it.

Snippet (4):
------------

class MyClass {
private:
MyClass(MyClass const &); /* Can't copy-construct! */

public:
MyClass() {}
};

int main()
{
MyClass const &r = MyClass();
}

--

Frederick Gotham
Back to top
Victor Bazarov
Guest





PostPosted: Sun Jul 30, 2006 1:42 am    Post subject: Re: Lifetime extension misconception Reply with quote



Frederick Gotham wrote:
Quote:
There is a common misconception, (one which I myself also held at one
point), that a const reference can "extend the lifetime of a
temporary". Examples such as the following are given:

Snippet (1)
-----------

#include <string
using std::string;

#include <iostream
using std::cout;

string Func()
{
return "Hello";
}

int main()
{
string const &str = Func();

cout << str << '\n';
}

In the above snippet, no temporary "has had its lifetime extended".
If such a thing were true, then the following code would be perfectly
OK:

Snippet (2):
------------

#include <string
using std::string;

string Func()
{
return "Hello";
}

int main()
{
string const &cstr = Func();

string &str = const_cast<string&>(cstr);

str = "World";
}


But alas, Snippet (2) exhibits undefined behaviour, because the
reference does not refer to the original non-const object which was
returned by value from the function.

The code in Snippet (1) works on exactly the same principle as the
following code snippet:

Snippet (3):
------------

int main()
{
int const &r = 5;
}

In Snippet (1) and in Snippet (3), the const reference remains valid
NOT because a temporary has had its liftime extended, but because the
reference was initialised with an R-value. The C++ Standard defines
this process:

If the initializer expression is an rvalue, with T2 a class type, and
“cv1 T1” is reference-compatible with “cv2 T2,” the reference is
bound in one of the following ways (the choice is
implementation-defined):
— The reference is bound to the object represented by the rvalue (see
3.10) or to a sub-object within that object.
— A temporary of type “cv1 T2” [sic] is created, and a constructor is
called to copy the entire rvalue object into the temporary. The
reference is bound to the temporary or to a sub-object within the
temporary.

This explains why the following code snippet fails to compile, and
disproves that the lifetime of a temporary is extended by binding a
const reference to it.

Snippet (4):
------------

class MyClass {
private:
MyClass(MyClass const &); /* Can't copy-construct! */

public:
MyClass() {}
};

int main()
{
MyClass const &r = MyClass();
}

Here is another interesting example:

char const* hello() { return "Hello"; }

#include <string>
#include <iostream>

int main() {
std::string const& str = hello();
std::cout << str << std::endl;
}

The temporary is not returned from anywhere, it's created as the result
of the initialisation of the reference. There is no lifetime "extention",
only the lifetime of the temporary to which the reference is bound. If
it is the original temporary, you can think of it as "extention" of its
lifetime, but the point you made with your private copy-c-tor constructor
is that it doesn't have to be the original temporary. It could just as
well be *another* temporary, copy-constructed from the "original" or from
something else, like in my example.

Just like in any other situation with returning by value, the copy-c-tor
has to be available for the code to be legal, even if copying is not done.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Back to top
Old Wolf
Guest





PostPosted: Mon Jul 31, 2006 9:10 am    Post subject: Re: Lifetime extension misconception Reply with quote



Frederick Gotham wrote:
Quote:
There is a common misconception, (one which I myself also held at one point),
that a const reference can "extend the lifetime of a temporary".

That is not a misconception.

Quote:
#include <string
using std::string;

#include <iostream
using std::cout;

string Func()
{
return "Hello";
}

int main()
{
string const &str = Func();

cout << str << '\n';
}

In the above snippet, no temporary "has had its lifetime extended".

The return value of Func() is a temporary. It has its lifetime extended
by being bound to 'str'.

If it did not have its lifetime extended, then the cout << str would be
referencing an object that no longer existed.

Quote:
If such a thing were true, then the following code would be perfectly OK:

Snippet (2):
------------

#include <string
using std::string;

string Func()
{
return "Hello";
}

int main()
{
string const &cstr = Func();

string &str = const_cast<string&>(cstr);

str = "World";
}

yes, that code is OK.

Quote:
But alas, Snippet (2) exhibits undefined behaviour,

No it doesn't.

Quote:
because the reference does not refer to the original non-const object
which was returned by value from the function.

The reference refers to the return value of the function, not the
original object that was returned by value, as you say.

Quote:
The code in Snippet (1) works on exactly the same principle as the following
code snippet:

Snippet (3):
------------

int main()
{
int const &r = 5;
}

In Snippet (1) and in Snippet (3), the const reference remains valid NOT
because a temporary has had its liftime extended,

That code creates a temporary int , initializes it to 5, and then
binds 'r' to it. The temporary has its lifetime extended to the
scope of 'r'.

Quote:
but because the reference was initialised with an R-value.
The C++ Standard defines this process:

- A temporary of type "cv1 T2" [sic] is created, and a constructor is called
to copy the entire rvalue object into the temporary. The reference is bound
to the temporary or to a sub-object within the temporary.

Yes, that is what happened. A temporary of type "int" was created,
and its "copy constructor" was used to initialize it with 5. The
reference
is then bound to the temporary, and that temporary's lifetime is
extended.

I put "copy constructor" in quotes because ints don't really have copy
constructors. The string example is more straight forward.

Quote:
This explains why the following code snippet fails to compile
and disproves that the lifetime of a temporary is extended by binding
a const reference to it.

It does no such thing.
Quote:

Snippet (4):
------------

class MyClass {
private:
MyClass(MyClass const &); /* Can't copy-construct! */

public:
MyClass() {}
};

int main()
{
MyClass const &r = MyClass();
}

This fails to compile because the standard explicitly says that a
copy constructor is needed when initializing a reference with
a temporary. In fact you quoted that section of the standard earlier.

In this whole thread, I think you are confusing the object being
returned, with the return value. The return value (a temporary)
exists in the scope of the calling function, and is copy-constructed
from the object being returned (which exists in the scope of the
called function).

Normally the return value is destroyed at the end of the full-
expression, since it is a temporary. But when it is bound to
a const reference, it is not destroyed.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.