Understanding temporary objects / taking address

Discussion in 'C++' started by Henning Hasemann, Jun 28, 2006.

  1. I have a function which gets the adress of an object as argument.
    It does some comparsion with the object's contents and then returns.
    no Reference or pointer to the object is stored or will be used after
    the function has returned.

    Say the function whould be named f and the objects class whould be T
    it'll look like this:

    bool f(T* thing) {
    return thing->foobar == 5; // Just a stupid example
    }

    When I now write a piece of code like this:

    bool yesorno = f(&T(77));

    I get a warning because I take the address of a temporary object.
    Im not sure if this is okay or not here.
    Does the object live long enough so f can do its operations on it?

    Is it generally a good idea to to such things?
    Or should I create an extra local variable which holds T(77)?
    (As I will have lots of these calls that whould be unhandy as I use
    different subclasses of T and you can Imagine using new and delete for
    every call whuld be even unhandier.)

    TIA
    Henning
    Henning Hasemann, Jun 28, 2006
    #1
    1. Advertising

  2. Henning Hasemann

    Daniel T. Guest

    In article <e7u850$2mr$-bs.de>,
    Henning Hasemann <> wrote:

    > I have a function which gets the adress of an object as argument.
    > It does some comparsion with the object's contents and then returns.
    > no Reference or pointer to the object is stored or will be used after
    > the function has returned.
    >
    > Say the function whould be named f and the objects class whould be T
    > it'll look like this:
    >
    > bool f(T* thing) {
    > return thing->foobar == 5; // Just a stupid example
    > }
    >
    > When I now write a piece of code like this:
    >
    > bool yesorno = f(&T(77));
    >
    > I get a warning because I take the address of a temporary object.
    > Im not sure if this is okay or not here.
    > Does the object live long enough so f can do its operations on it?
    >
    > Is it generally a good idea to to such things?
    > Or should I create an extra local variable which holds T(77)?
    > (As I will have lots of these calls that whould be unhandy as I use
    > different subclasses of T and you can Imagine using new and delete for
    > every call whuld be even unhandier.)


    Try changing 'f' to:

    bool f( const T* thing );
    Daniel T., Jun 28, 2006
    #2
    1. Advertising

  3. Henning Hasemann

    Howard Guest

    "Henning Hasemann" <> wrote in message
    news:e7u850$2mr$-bs.de...
    >I have a function which gets the adress of an object as argument.
    > It does some comparsion with the object's contents and then returns.
    > no Reference or pointer to the object is stored or will be used after
    > the function has returned.
    >
    > Say the function whould be named f and the objects class whould be T
    > it'll look like this:
    >
    > bool f(T* thing) {
    > return thing->foobar == 5; // Just a stupid example
    > }
    >
    > When I now write a piece of code like this:
    >
    > bool yesorno = f(&T(77));
    >
    > I get a warning because I take the address of a temporary object.
    > Im not sure if this is okay or not here.
    > Does the object live long enough so f can do its operations on it?
    >
    > Is it generally a good idea to to such things?
    > Or should I create an extra local variable which holds T(77)?
    > (As I will have lots of these calls that whould be unhandy as I use
    > different subclasses of T and you can Imagine using new and delete for
    > every call whuld be even unhandier.)


    I'd prefer to use a const reference as the parameter, myself. That lets you
    pass a temporary object fine, with no warnings, (and also handles the
    polymorphism correctly, just like a pointer). I only use pointers if I have
    to.

    -Howard
    Howard, Jun 28, 2006
    #3
  4. Henning Hasemann posted:


    > Say the function whould be named f and the objects class whould be T
    > it'll look like this:
    >
    > bool f(T* thing) {
    > return thing->foobar == 5; // Just a stupid example
    > }
    >
    > When I now write a piece of code like this:
    >
    > bool yesorno = f(&T(77));
    >
    > I get a warning because I take the address of a temporary object.
    > Im not sure if this is okay or not here.



    That warning should be an error.

    A temporary, nameless object is an R-value. You can't take the address of
    a R-value.

    If you really want to pass the address of a temporary to a function, try
    this:

    class ArbitraryClass {
    public:
    int a;
    int b;

    ArbitraryClass() : a(1), b(2) {}
    };

    bool Func( const ArbitraryClass *p )
    {
    return p->a == p->b;
    }

    template<class T>
    const T *AdrsTmp( const T &temp ) { return &temp; }


    int main()
    {
    Func( AdrsTmp( ArbitraryClass() ) );
    }


    A temporary lives on until the end of the statement; so the temporary in
    the above code gets killed at the end of the semi-colon in "main".

    I wonder what people would think if I rewrote "AdrsTmp" like as follows:

    template<class T>
    T *AdrsTmp( const T &temp ) { return const_cast<T*>(&temp); }


    We know that it's pefectly okay to cast away constness if the object in
    question is in fact non-const. The temporary in "main" is non-const --
    that's for sure. However... is the "AdrsTmp" function free to create
    another temporary when it takes its argument, rather than work with the
    temporary provided by main... ?


    --

    Frederick Gotham
    Frederick Gotham, Jun 28, 2006
    #4
  5. Howard wrote:

    > I'd prefer to use a const reference as the parameter, myself. That lets you
    > pass a temporary object fine, with no warnings, (and also handles the
    > polymorphism correctly, just like a pointer). I only use pointers if I have
    > to.


    In this case I have to, as f actually is the contains() method of a
    set-template-class and the template Parameter is a pointer type but
    could be a non-pointer type as well.

    I think Daniel T.'s solution with using a const pointer was what I was
    looking for.

    Thanks you 2.

    Henning
    Henning Hasemann, Jun 28, 2006
    #5
  6. Frederick Gotham wrote:
    > Henning Hasemann posted:
    > A temporary lives on until the end of the statement; so the temporary in
    > the above code gets killed at the end of the semi-colon in "main".


    Hmm.
    Shouldnt this be long enough then? At the end of the semicolon Func has
    returned, so I got what I needed, or?

    I think I half-way understood your wrapper but (still) not exactly why
    it is necessary.
    If it is such a problem to give away the adress of a temporary, is there
    a better way in my case?

    Maybe I should tell a bit more od what Im doing. The function I talk
    about is the contains-Method of a template-class for a set (Yes I know
    of STL, there are reasons for implementing my own).

    It looks roughly like this:

    template<class T>
    class MySet {
    public:
    // ...
    bool contains(const T item) const {
    // look at item and return true if
    // we have something that is considered to be equal
    // ...
    }
    };

    The problematic case is the one, where T is a pointer-type.
    As I put different subclasses of T into this set and often look if a
    certain item is contained a (to the caller of contains()) local variable
    is as unpleasant as creating and deleting objects for each contains() on
    the heap.

    Henning
    Henning Hasemann, Jun 28, 2006
    #6
  7. Going through the formalities

    Henning Hasemann posted:

    > Frederick Gotham wrote:
    >> Henning Hasemann posted:
    >> A temporary lives on until the end of the statement; so the temporary
    >> in the above code gets killed at the end of the semi-colon in "main".

    >
    > Hmm.
    > Shouldnt this be long enough then? At the end of the semicolon Func
    > has returned, so I got what I needed, or?



    Yes, exactly.


    > I think I half-way understood your wrapper but (still) not exactly why
    > it is necessary.
    > If it is such a problem to give away the adress of a temporary, is
    > there a better way in my case?



    Well you can continue on with what you're doing, i.e. just stick the
    "address of" operator before a nameless temporary:

    &ArbitraryClass()

    but the C++ Standard forbids this, because you're taking the address of
    an R-value. Your compiler is being lenient by letting you do it.

    My own code however is perfectly Standard-compliant, because I don't take
    the address of an R-value. (Once the object gets bound to a const
    reference, you can use the const reference as an L-value).

    It's sort of like walking to the checkout with your wife, aiming to buy 6
    packets of Aspirin. In line with the Laws of the Land, the cashier
    informs you that he can only sell you a maximum of 3 packets, so you tell
    him "That's fine", and you just buy 3 packets. Having finalised the
    transaction, you then hand the rest of the money to your wife, and she
    buys another 3 packets of Aspirin. Sure, it isn't exactly how things are
    supposed to work, but by going through the formalities, you haven't
    broken the rules.

    Think of my template function as your wife ; )

    --

    Frederick Gotham
    Frederick Gotham, Jun 28, 2006
    #7
  8. Re: Going through the formalities

    Frederick Gotham wrote:
    > Henning Hasemann posted:
    > but the C++ Standard forbids this, because you're taking the address of
    > an R-value. Your compiler is being lenient by letting you do it.


    Ah okay.
    That surprises me a bit though. As I use "g++ (GCC) 3.3.6" with -ansi I
    thought it whould be already very strict.

    > It's sort of like walking to the checkout with your wife, aiming to buy 6
    > packets of Aspirin. In line with the Laws of the Land, the cashier
    > informs you that he can only sell you a maximum of 3 packets, so you tell
    > him "That's fine", and you just buy 3 packets. Having finalised the
    > transaction, you then hand the rest of the money to your wife, and she
    > buys another 3 packets of Aspirin. Sure, it isn't exactly how things are
    > supposed to work, but by going through the formalities, you haven't
    > broken the rules.
    >
    > Think of my template function as your wife ; )


    Well okay, i finally got the point :)

    I'll just leave it the dirty way for now and consider to use your
    "adapter" or something else when theres time, fortunately the warning
    will remind me sometimes of this.

    Thanks for you time :)

    Henning
    Henning Hasemann, Jun 28, 2006
    #8
  9. On Wed, 28 Jun 2006 18:01:58 +0200, Henning Hasemann
    <> wrote:
    >Howard wrote:
    >> I'd prefer to use a const reference as the parameter, myself. That lets you
    >> pass a temporary object fine, with no warnings, (and also handles the
    >> polymorphism correctly, just like a pointer). I only use pointers if I have
    >> to.

    >
    >In this case I have to, as f actually is the contains() method of a
    >set-template-class and the template Parameter is a pointer type but
    >could be a non-pointer type as well.


    If you have to use pointers (which is not actually clear from your
    answer) you should handle pointers appropriately:

    bool f (const T* thing) {
    return thing && thing->foobar == 5; // Just a stupid example
    }

    Best wishes,
    Roland Pibinger
    Roland Pibinger, Jun 28, 2006
    #9
  10. Re: Going through the formalities

    Henning Hasemann posted:

    > I'll just leave it the dirty way for now and consider to use your
    > "adapter" or something else when theres time, fortunately the warning
    > will remind me sometimes of this.



    Of course, you could use a simple static_cast:


    #include <string>

    void Func( const std::string * );

    int main()
    {
    Func( &static_cast<const std::string &>( std::string() ) );
    }



    --

    Frederick Gotham
    Frederick Gotham, Jun 28, 2006
    #10
  11. Henning Hasemann

    Ron Natalie Guest

    Henning Hasemann wrote:

    > bool yesorno = f(&T(77));
    >
    > I get a warning because I take the address of a temporary object.
    > Im not sure if this is okay or not here.
    > Does the object live long enough so f can do its operations on it?


    It's not OK to apply & to a non-lvalue. The language says unary-&
    gets applied to an lvalue (for simple pointers) or a qualified-id
    (for poitner to member).
    Ron Natalie, Jun 29, 2006
    #11
  12. Henning Hasemann

    Ron Natalie Guest

    Daniel T. wrote:

    > Try changing 'f' to:
    >
    > bool f( const T* thing );


    How does that help. The error is not in the call to f() but
    in the illegal application of unary& to an rvalue.
    Ron Natalie, Jun 29, 2006
    #12
  13. Henning Hasemann

    Ron Natalie Guest

    Henning Hasemann wrote:

    > In this case I have to, as f actually is the contains() method of a
    > set-template-class and the template Parameter is a pointer type but
    > could be a non-pointer type as well.
    >
    > I think Daniel T.'s solution with using a const pointer was what I was
    > looking for.
    >

    No it's not. It's just as wrong as you had before.
    Ron Natalie, Jun 29, 2006
    #13
  14. Henning Hasemann

    mangesh Guest

    Hi ,
    u have writtten " The temporary in "main" is non-const -- that's for
    sure. "
    Is constantness of temporary object compiler dependent ? Because
    somewhere on
    net i remember reading that temporary object created by compiler are
    constant , but i can't recall name of compiler .

    Regards ,
    Mangesh Sawant .


    Frederick Gotham wrote:
    > Henning Hasemann posted:
    >
    >
    > > Say the function whould be named f and the objects class whould be T
    > > it'll look like this:
    > >
    > > bool f(T* thing) {
    > > return thing->foobar == 5; // Just a stupid example
    > > }
    > >
    > > When I now write a piece of code like this:
    > >
    > > bool yesorno = f(&T(77));
    > >
    > > I get a warning because I take the address of a temporary object.
    > > Im not sure if this is okay or not here.

    >
    >
    > That warning should be an error.
    >
    > A temporary, nameless object is an R-value. You can't take the address of
    > a R-value.
    >
    > If you really want to pass the address of a temporary to a function, try
    > this:
    >
    > class ArbitraryClass {
    > public:
    > int a;
    > int b;
    >
    > ArbitraryClass() : a(1), b(2) {}
    > };
    >
    > bool Func( const ArbitraryClass *p )
    > {
    > return p->a == p->b;
    > }
    >
    > template<class T>
    > const T *AdrsTmp( const T &temp ) { return &temp; }
    >
    >
    > int main()
    > {
    > Func( AdrsTmp( ArbitraryClass() ) );
    > }
    >
    >
    > A temporary lives on until the end of the statement; so the temporary in
    > the above code gets killed at the end of the semi-colon in "main".
    >
    > I wonder what people would think if I rewrote "AdrsTmp" like as follows:
    >
    > template<class T>
    > T *AdrsTmp( const T &temp ) { return const_cast<T*>(&temp); }
    >
    >
    > We know that it's pefectly okay to cast away constness if the object in
    > question is in fact non-const. The temporary in "main" is non-const --
    > that's for sure. However... is the "AdrsTmp" function free to create
    > another temporary when it takes its argument, rather than work with the
    > temporary provided by main... ?
    >
    >
    > --
    >
    > Frederick Gotham
    mangesh, Jun 29, 2006
    #14
  15. Henning Hasemann

    Ian Collins Guest

    mangesh wrote:

    Please don't top post and use gibberish such as 'u'.

    > Frederick Gotham wrote:


    >>
    >>template<class T>
    >>const T *AdrsTmp( const T &temp ) { return &temp; }
    >>
    >>
    >>int main()
    >>{
    >> Func( AdrsTmp( ArbitraryClass() ) );
    >>}
    >>
    >>
    >>A temporary lives on until the end of the statement; so the temporary in
    >>the above code gets killed at the end of the semi-colon in "main".
    >>
    >>I wonder what people would think if I rewrote "AdrsTmp" like as follows:
    >>
    >>template<class T>
    >>T *AdrsTmp( const T &temp ) { return const_cast<T*>(&temp); }
    >>
    >>
    >>We know that it's pefectly okay to cast away constness if the object in
    >>question is in fact non-const. The temporary in "main" is non-const --
    >>that's for sure. However... is the "AdrsTmp" function free to create
    >>another temporary when it takes its argument, rather than work with the
    >>temporary provided by main... ?
    >>

    > Hi ,
    > u have writtten " The temporary in "main" is non-const -- that's for
    > sure. "
    > Is constantness of temporary object compiler dependent ? Because
    > somewhere on
    > net i remember reading that temporary object created by compiler are
    > constant , but i can't recall name of compiler .
    >

    No, the temporary is an rvalue. It can be assigned to a const
    reference, but as a value, you can take it's address. All the wrapper
    does is assign it to a const reference and take the address of the
    reference.

    A bit like:

    const int& i = 42;

    const int* p = &i;

    42 is an rvalue, so you can assign it to a const reference, but you
    couldn't take its address.

    --
    Ian Collins.
    Ian Collins, Jun 29, 2006
    #15
  16. Henning Hasemann

    Daniel T. Guest

    In article <44a325af$0$18520$>,
    Ron Natalie <> wrote:

    > Daniel T. wrote:
    >
    > > Try changing 'f' to:
    > >
    > > bool f( const T* thing );

    >
    > How does that help. The error is not in the call to f() but
    > in the illegal application of unary& to an rvalue.


    It doesn't. Sorry, I was wrong to suggest it.
    Daniel T., Jun 29, 2006
    #16
  17. mangesh posted:


    > Hi , u have writtten " The temporary in "main" is non-const -- that's
    > for sure. " Is constantness of temporary object compiler dependent ?
    > Because somewhere on net i remember reading that temporary object
    > created by compiler are constant , but i can't recall name of compiler
    > .


    And I'm glad you can't remember the name of any such compiler.

    Let's start off with writing a very simple class which has a member
    function which comes in two flavours: The const flavour, and the non-
    const flavour.

    #include <iostream>

    class Arb {
    public:

    int a;


    void Method()
    {
    a = 7;

    std::cout << "The NON-const method was called.\n";
    }

    void Method() const
    {
    std::cout << "The CONST method was called.\n";
    }


    };


    Now let's make two typedef's:

    typedef Arb NonConstArb;
    typedef Arb const ConstArb;


    And now let's create two nameless temporaries, one which we intend to be
    const, and the other which we intend to be non-const:


    int main()
    {
    NonConstArb();

    ConstArb();
    }


    And now let's invoke our member function upon each of them and see what
    happens:


    int main()
    {
    NonConstArb().Method();

    ConstArb().Method();
    }


    I hope the output pleases you.


    --

    Frederick Gotham
    Frederick Gotham, Jun 29, 2006
    #17
  18. Henning Hasemann

    mangesh Guest

    Hi ,
    thanks for clearing my doubt .

    Regrds ,
    Mangesh .

    Frederick Gotham wrote:
    > mangesh posted:
    >
    >
    > > Hi , u have writtten " The temporary in "main" is non-const -- that's
    > > for sure. " Is constantness of temporary object compiler dependent ?
    > > Because somewhere on net i remember reading that temporary object
    > > created by compiler are constant , but i can't recall name of compiler
    > > .

    >
    > And I'm glad you can't remember the name of any such compiler.
    >
    > Let's start off with writing a very simple class which has a member
    > function which comes in two flavours: The const flavour, and the non-
    > const flavour.
    >
    > #include <iostream>
    >
    > class Arb {
    > public:
    >
    > int a;
    >
    >
    > void Method()
    > {
    > a = 7;
    >
    > std::cout << "The NON-const method was called.\n";
    > }
    >
    > void Method() const
    > {
    > std::cout << "The CONST method was called.\n";
    > }
    >
    >
    > };
    >
    >
    > Now let's make two typedef's:
    >
    > typedef Arb NonConstArb;
    > typedef Arb const ConstArb;
    >
    >
    > And now let's create two nameless temporaries, one which we intend to be
    > const, and the other which we intend to be non-const:
    >
    >
    > int main()
    > {
    > NonConstArb();
    >
    > ConstArb();
    > }
    >
    >
    > And now let's invoke our member function upon each of them and see what
    > happens:
    >
    >
    > int main()
    > {
    > NonConstArb().Method();
    >
    > ConstArb().Method();
    > }
    >
    >
    > I hope the output pleases you.
    >
    >
    > --
    >
    > Frederick Gotham
    mangesh, Jun 30, 2006
    #18
    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. Replies:
    0
    Views:
    1,107
  2. Replies:
    3
    Views:
    707
  3. Replies:
    7
    Views:
    3,169
    James Kanze
    Feb 12, 2008
  4. Andy Gibbs
    Replies:
    5
    Views:
    4,002
    Andy Gibbs
    Nov 19, 2008
  5. V.Subramanian, India

    taking address of temporary object

    V.Subramanian, India, Feb 10, 2012, in forum: C++
    Replies:
    2
    Views:
    998
    Alf P. Steinbach
    Feb 10, 2012
Loading...

Share This Page