Problem "taking address of temporary"

Discussion in 'C++' started by Andy Gibbs, Nov 18, 2008.

  1. Andy Gibbs

    Andy Gibbs Guest

    Hello,

    I have a problem with the following example code:

    #include <stdio.h>

    class Test
    {
    public:
    Test(char* str)
    {
    printf("ctor\n");
    _str = str;
    }

    ~Test()
    {
    printf("dtor\n");
    }

    char* _str;
    };

    void Function(const Test* const t)
    {
    if (t) printf("str=%s\n", t->_str);
    else printf("null\n");
    }

    int main(int argc, char *argv[])
    {
    printf("test1:\n");
    { Test t("test1"); Function(&t); }

    printf("test2:\n");
    Function(&Test("test2"));

    printf("test3:\n");
    Function(0);
    }


    The problem comes in the line "Function(&Test("test2"));" with the
    warning "taking address of temporary". I am using GCC 4.1.2. However, the
    code runs as expected with the following output:

    test1:
    ctor
    str=test1
    dtor
    test2:
    ctor
    str=test2
    dtor
    test3
    null

    The code above demonstrates that the Test object is not destroyed until
    after Function is called, so I cannot see why the compiler complains about
    this. However, for my actual application, this particular syntax is what I
    require in order to keep the code at its most legible, and so I really hope
    to find a solution to this warning.

    Is there some way I should alter the signature of Function to stop the
    warning? Is there a compiler option to ignore this specific warning (e.g.
    a #pragma or something)?

    Thanks for any help!

    Andy
    Andy Gibbs, Nov 18, 2008
    #1
    1. Advertising

  2. Andy Gibbs

    James Kanze Guest

    On Nov 18, 5:50 pm, Pete Becker <> wrote:
    > On 2008-11-18 10:52:48 -0500, Andy Gibbs <> said:
    > > The problem comes in the line "Function(&Test("test2"));"
    > > with the warning "taking address of temporary". I am using
    > > GCC 4.1.2. However, the code runs as expected with the
    > > following output:


    > > test1:
    > > ctor
    > > str=test1
    > > dtor
    > > test2:
    > > ctor
    > > str=test2
    > > dtor
    > > test3
    > > null


    > > The code above demonstrates that the Test object is not
    > > destroyed until after Function is called, so I cannot see
    > > why the compiler complains about this.


    > The compiler warns about it because the code takes the address
    > of a temporary, although there's nothing inherently wrong with
    > doing that.


    Has this changed in the latest draft. According to my copy of
    the standard (version 1998---out of date, I know), "The
    operand [of the unary & operator] shall be an lvalue or a
    qualified-id". His expression was &Test("test2"); IMHO, the
    compiler generated a warning because it was being laxist.

    If I compile his code with Sun CC, I get:
    "addrtemp.cc", line 34: Warning, badargtypel2w: String literal
    converted to char* in formal argument str in call to Test::Test
    (char*).
    "addrtemp.cc", line 37: Warning, badargtypel2w: String literal
    converted to char* in formal argument str in call to Test::Test
    (char*).
    "addrtemp.cc", line 37: Error, wantvarname: The "&" operator can
    only be applied to a variable or other l-value.
    Which is what I'd expect from a good compiler. Curiously
    enough, g++ only generates says:
    addrtemp.cc: In function 'int main(int, char**)':
    addrtemp.cc:37: warning: taking address of temporary
    even with -std=c++98 -pedantic (I'd call this a bug), and VC++
    doesn't say anything.

    > If you misuse the result you can get in trouble. Apparently
    > the writers of your compiler thnk that you can't be trusted to
    > use that address without screwing up.


    Apparently, the writers of his compiler don't care about the
    standard. (Nothing new there.) And it's the members of the
    stadnards committee who think you can't be trusted. (Or just
    wanted to remain compatible with C in this respect.)

    --
    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, Nov 18, 2008
    #2
    1. Advertising

  3. Andy Gibbs wrote:
    >
    > The problem comes in the line "Function(&Test("test2"));" with the
    > warning "taking address of temporary". I am using GCC 4.1.2. However, the
    > code runs as expected with the following output:
    >
    > test1:
    > ctor
    > str=test1
    > dtor
    > test2:
    > ctor
    > str=test2
    > dtor
    > test3
    > null
    >
    > The code above demonstrates that the Test object is not destroyed until
    > after Function is called, so I cannot see why the compiler complains about
    > this.


    The compiler complains about this because it is _illegal_ in C++ to take
    the address of a temporary. Temporary objects are not lvalues in C++,
    which means that unary '&' is not applicable to them. Your program is
    ill-formed, meaning that the attempt to take address is what is normally
    called an "error". Your compiler issues a mere "warning" simply because
    it decided to allow you to take the address as a compiler-specific
    language extension, but at the same time wants to stick with the
    standard requirement to issue a "diagnostic message" in case of an
    ill-formed program.

    Also, an experiment with the code doesn't really "demonstrate" anything
    reliably.

    > However, for my actual application, this particular syntax is what I
    > require in order to keep the code at its most legible, and so I really hope
    > to find a solution to this warning.


    I'd recommend you to stick with well-formed code. I.e. stop trying to
    get the address of a temporary.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Nov 18, 2008
    #3
  4. Victor Bazarov wrote:
    >
    > There is an inherent controversy around this. Example:
    >
    > struct Foo {
    > Foo(int) {}
    > Foo& that() { return *this; }
    > };
    >
    > int main() {
    > Foo(42); // expression that yields an rvalue
    > Foo(42).that(); // expression that is an lvalue
    > }
    >
    > How would you explain that? :) You can't avoid being "laxist" with the
    > language that contains such pearls.
    > ...


    There's an inherent controversy around everything, if you dig deep
    enough. Your example is not really different from, say

    const int* addr(const int& i) { return &i; }

    int main() {
    const int* p = addr(42);
    }

    You think this is a "pearl"? I'd say this is just a necessary evil one
    has to remember about.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Nov 18, 2008
    #4
  5. Andy Gibbs

    James Kanze Guest

    On Nov 18, 6:53 pm, Victor Bazarov <> wrote:
    > James Kanze wrote:


    [...]
    > >> The compiler warns about it because the code takes the
    > >> address of a temporary, although there's nothing inherently
    > >> wrong with doing that.


    > > Has this changed in the latest draft.  According to my copy of
    > > the standard (version 1998---out of date, I know), "The
    > > operand [of the unary & operator] shall be an lvalue or a
    > > qualified-id".  His expression was &Test("test2"); IMHO, the
    > > compiler generated a warning because it was being laxist.
    > > [..]


    > There is an inherent controversy around this.  Example:


    >     struct Foo {
    >         Foo(int) {}
    >         Foo& that() { return *this; }
    >     };


    >     int main() {
    >        Foo(42);        // expression that yields an rvalue
    >        Foo(42).that(); // expression that is an lvalue
    >     }


    > How would you explain that? :)


    I wouldn't try to:). But the language standard defines a
    concept of lvalue and rvalue, or at least insists that they
    exist, that certain expressions return lvalues, others rvalues,
    and that certain operators require lvalues, others rvalues (and
    that there is an lvalue to rvalue conversion---so that in
    something like i=j, where both i and j have type int, there is
    an implicit conversion involved). The language says that the
    expression Test("test1") is an rvalue, and it says that unary &
    requires an lvalue, and so be it.

    > You can't avoid being "laxist" with the language that contains
    > such pearls.


    Such "pearls" are probably inevitable as soon as you try to
    maintain the distinction between lvalues and rvalues, and also
    have real objects. (At one point, I actually suggested that we
    drop the concept of lvalue/rvalue completely, and simply state
    that all temporaries were considered const. This would have
    allowed things like &3, with type int const, but after all, we
    allow this indirectly already, if you bind 3 to a const
    reference, and then take its address.)

    --
    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, Nov 18, 2008
    #5
  6. Andy Gibbs

    Andy Gibbs Guest

    Andy Gibbs wrote:

    > Hello,
    >
    > I have a problem with the following example code:
    >
    > ...


    Hello all,

    Thanks for all your comments and recommendations!

    Cheers
    Andy
    Andy Gibbs, Nov 19, 2008
    #6
    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,111
  2. Replies:
    3
    Views:
    710
  3. Replies:
    7
    Views:
    3,179
    James Kanze
    Feb 12, 2008
  4. Mike

    Problem problem problem :( Need Help

    Mike, May 7, 2004, in forum: ASP General
    Replies:
    2
    Views:
    530
    Bullschmidt
    May 11, 2004
  5. V.Subramanian, India

    taking address of temporary object

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

Share This Page