Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > lifetime of tempory generated variables

Reply
Thread Tools

lifetime of tempory generated variables

 
 
mario semo
Guest
Posts: n/a
 
      05-14-2008
Hello,

What does the C++ Norm says about the lifetime of compiler generated
temporary variables?

#include <stdio.h>

class BaseRef
{
//--------------------------------------------------------------------------
public:
//--------------------------------------------------------------------------

BaseRef()
{
printf("ctor BaseRef %p\n",this);
}

virtual ~BaseRef()
{
printf("dtor BaseRef %p\n",this);
}

void *qPtr()
{
return 0;
}
};

class Server
{
//--------------------------------------------------------------------------
public:
//--------------------------------------------------------------------------

Server()
{
}

virtual ~Server()
{
}

BaseRef queryBaseRef()
{
return BaseRef();
}

};

int main(int argc,char *argv[])
{
Server lServer;

printf("start\n");
{
// generates a temporary baseRef instance.
void * lPtr = lServer.queryBaseRef().qPtr();
printf("before }\n");
}
printf("after }\n");
printf("done\n");

return 0;
}


Here is the output of 2 different compilers:

VC9
start
ctor BaseRef 0012FF6C
dtor BaseRef 0012FF6C
before }
after }
done

VACPP
start
ctor BaseRef 12FF88
before }
dtor BaseRef 12FF88
after }
done



regards,

mario semo

 
Reply With Quote
 
 
 
 
gnuyuva
Guest
Posts: n/a
 
      05-14-2008
On May 14, 7:56 pm, "mario semo" <(E-Mail Removed)> wrote:
> Hello,
>
> What does the C++ Norm says about the lifetime of compiler generated
> temporary variables?
>
> #include <stdio.h>
>
> class BaseRef
> {
> //--------------------------------------------------------------------------
> public:
> //--------------------------------------------------------------------------
>
> BaseRef()
> {
> printf("ctor BaseRef %p\n",this);
> }
>
> virtual ~BaseRef()
> {
> printf("dtor BaseRef %p\n",this);
> }
>
> void *qPtr()
> {
> return 0;
> }
>
> };
>
> class Server
> {
> //--------------------------------------------------------------------------
> public:
> //--------------------------------------------------------------------------
>
> Server()
> {
> }
>
> virtual ~Server()
> {
> }
>
> BaseRef queryBaseRef()
> {
> return BaseRef();
> }
>
> };
>
> int main(int argc,char *argv[])
> {
> Server lServer;
>
> printf("start\n");
> {
> // generates a temporary baseRef instance.
> void * lPtr = lServer.queryBaseRef().qPtr();
> printf("before }\n");
> }
> printf("after }\n");
> printf("done\n");
>
> return 0;
>
> }
>
> Here is the output of 2 different compilers:
>
> VC9
> start
> ctor BaseRef 0012FF6C
> dtor BaseRef 0012FF6C
> before }
> after }
> done
>
> VACPP
> start
> ctor BaseRef 12FF88
> before }
> dtor BaseRef 12FF88
> after }
> done
>
> regards,
>
> mario semo


The code generated by VC9 is more valid because it is guaranteed that
the lifetimes of the temporaries returned by value are valid till the
execution of the containing statement. So the temporary returned by
queryBaseRef is valid untill the qPtr() is evaluated. But the way the
code is generated by the compilers varies. GCC provides similar
results like VC9.
 
Reply With Quote
 
 
 
 
Marcel Müller
Guest
Posts: n/a
 
      05-14-2008
mario semo schrieb:
> What does the C++ Norm says about the lifetime of compiler generated
> temporary variables?


Until the next statement.

> // generates a temporary baseRef instance.
> void * lPtr = lServer.queryBaseRef().qPtr();


lPtr is now a dangling reference and must mot be dereferenced anymore..

> printf("before }\n");
> }
> printf("after }\n");



> Here is the output of 2 different compilers:
>
> VC9
> start
> ctor BaseRef 0012FF6C
> dtor BaseRef 0012FF6C
> before }
> after }
> done


This is standard conform.

> VACPP
> start
> ctor BaseRef 12FF88
> before }
> dtor BaseRef 12FF88
> after }
> done


Here I am unsure.
As far as I know this is wrong, bcause the object must be destroyed
before the next statement. But maybe it /can/ be destroyed before the
next statement. Anyway it is undefined behaviour to rely in the object
existence after the statement has finished.
Maybe the automatic inliner understood your implicit dependency.

But you may explicitly extend the lifetime of temporaries creating a
const reference.

const BaseRef& tmp = lServer.queryBaseRef();

Now the temporary is valid until the end of the block. No copy is made.


Marcel
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-15-2008
On May 14, 11:18 pm, Marcel Müller <(E-Mail Removed)>
wrote:
> mario semo schrieb:


> > What does the C++ Norm says about the lifetime of compiler
> > generated temporary variables?


> Until the next statement.


Until the end of the full expression in which they were
generated, with a few exceptions. Thus, for example, in:

if ( generateATemporary ) ...

the temporary does not last until the end of the if
statement---only until the end of the full expression in the
condition.

All of the exceptions extend the lifetime in some way, so you're
guaranteed at least until the end of the full expression in
every case. The most important extention is in an
initialization expression---the lifetime is extended until the
object is fully initialized, e.g.:

MyClass object( generateATemporary ) ;

The full expression is just "generateATemporary", but the
temporary is guaranteed to last until we return from the
contructor of object (which is not part of the expression, but
implicit in the fact that this is a definition of a class type).

> > // generates a temporary baseRef instance.
> > void * lPtr = lServer.queryBaseRef().qPtr();


> lPtr is now a dangling reference and must mot be dereferenced
> anymore..


> > printf("before }\n");
> > }
> > printf("after }\n");
> > Here is the output of 2 different compilers:


> > VC9
> > start
> > ctor BaseRef 0012FF6C
> > dtor BaseRef 0012FF6C
> > before }
> > after }
> > done


> This is standard conform.
>
> > VACPP
> > start
> > ctor BaseRef 12FF88
> > before }
> > dtor BaseRef 12FF88
> > after }
> > done


> Here I am unsure.


It's not conform. The standard says exactly when the destructor
must be called. Before the standard, however, the ARM (and
earlier language specifications) were considerably looser: the
destructor could be called anytime after the temporary was
"used" and before the next closing brace. Thus (assuming s is
std::string, or something with a similar interface), given:

char const* f( char const* ps )
{
std::cout << ps << std::endl ;
return ps ;
}

int
main()
{
std::string a( "abc" ), b( "123" ) ;
if ( 1 ) {
char const* p = f( (a + b).c_str() ) ;
// Note the temporary in the
// call to f...
std::cout << p << std::endl ;
}
}

According to the standard, the output in f is fine (since the
temporary will remain until the end of the full expression, i.e.
the return from f). With some pre-standard compilers, however
(including all CFront based compilers, which many considered the
de facto standard), this code was perfectly fine. With others
(g++, for example), both output failed, since the call to
std::string::c_str() "used" the temporary, and it could be
immediately destructed (before the call to f).

In general, those compilers with a shorter than standard
lifetime (e.g. g++) changed very rapidly to the standard
lifetime; extending the lifetime typically wouldn't break much
code. Those which had a longer lifetime, however, tended to be
very cautious about shortening it, since the potential for
breaking code was much greater---even today, Sun CC has options
to support both lifetimes: standard, and until the next closing
brace. (I'm not sure off hand which is the default in the last
version, but at least until very, very recently, it was the
extended lifetime.)

> But you may explicitly extend the lifetime of temporaries
> creating a const reference.


> const BaseRef& tmp = lServer.queryBaseRef();


> Now the temporary is valid until the end of the block. No copy
> is made.


The temporary which is actually bound to tmp has its lifetime
extended, but other temporaries in the expression don't. And
whether a copy is made or not depends on the implementation (but
the object must be copiable, although as far as I know, only g++
enforces this correctly).

--
James Kanze (GABI Software) email:(E-Mail Removed)
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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Put variables into member variables or function variables? tjumail@gmail.com C++ 9 03-23-2008 04:03 PM
Lifetime of member variables in C++ object nagashre@gmail.com C++ 3 11-01-2007 10:16 PM
Lifetime of member variables in C++ object nagashre@gmail.com C++ 1 11-01-2007 08:01 PM
lifetime of local variables Anargyros L. Papadopoulos C++ 1 01-21-2005 05:45 PM
RE Copying to a Tempory Third Hard Drive.. bonecrusher Computer Support 5 12-11-2004 10:35 PM



Advertisments