lifetime of tempory generated variables

Discussion in 'C++' started by mario semo, May 14, 2008.

  1. mario semo

    mario semo Guest

    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
    mario semo, May 14, 2008
    #1
    1. Advertising

  2. mario semo

    gnuyuva Guest

    On May 14, 7:56 pm, "mario semo" <> 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.
    gnuyuva, May 14, 2008
    #2
    1. Advertising

  3. 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
    Marcel Müller, May 14, 2008
    #3
  4. mario semo

    James Kanze Guest

    On May 14, 11:18 pm, Marcel Müller <>
    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:
    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
    James Kanze, May 15, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bruce W.1
    Replies:
    1
    Views:
    312
    Alvin Bruney [MVP]
    Jan 29, 2004
  2. bucrepus

    Variable Lifetime

    bucrepus, Apr 14, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    939
    bruce barker
    Apr 14, 2004
  3. Anargyros L. Papadopoulos

    lifetime of local variables

    Anargyros L. Papadopoulos, Jan 21, 2005, in forum: C++
    Replies:
    1
    Views:
    302
    Victor Bazarov
    Jan 21, 2005
  4. Replies:
    1
    Views:
    325
    Puppet_Sock
    Nov 1, 2007
  5. Replies:
    3
    Views:
    334
    Tadeusz Kopec
    Nov 1, 2007
Loading...

Share This Page