Taking address of temporary - workaround needed

16,843

Solution 1

Integer i(12);
foo(&i);

That gets rid of the "taking the address of a temporary" problem, which is what you have. You're not passing the address of a local variable (which the above does, and is indeed ok in this case), you're grabbing the address of a temporary.

Obviously, if foo tries to hold on to that pointer one way or another, you'll have issues down the line.

Solution 2

template<typename T> const T* rvalue_address(const T& in) {
    return &in;
}

In my opinion, it should be just as legal to take a const T* as a const T&, but this trivial function will handily perform the conversion.

Solution 3

GCC is wrong in this case. Your integer is an rvalue and taking the address of an rvalue is illegal.

§5.3.1 Unary operators, Section 3

The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id.

Clang gives an error in this case:

error: taking the address of a temporary object of type 'Integer' [-Waddress-of-temporary]
    foo( &Integer(12) );
         ^~~~~~~~~~~~
Share:
16,843
elcuco
Author by

elcuco

SOreadytohelp, yea, I don't like Reggae (I love it). But not twitter.

Updated on June 15, 2022

Comments

  • elcuco
    elcuco almost 2 years

    I am facing a GCC warning that I want to fix. Basically I am passing to a method a pointer to a local variable, which in my case is perfectly OK. I understand why the compiler tells me that this is a potential problem, but in my case this is OK.

    How can I workaround it, on a local space? Passing -fpermissive when compiling will make me fail to find future problems. I want to fix this specific problem, or workaround it.

    Code is available here:

    #include <cstdio>
    
    class Integer{
    public:
        Integer(int i ){ v = i; };
        int value(){ return v; };
    private:
        int v;
    };
    
    int foo(Integer *i);
    
    int main()
    {
        foo( &Integer(12) );
    }
    
    int foo(Integer *i)
    {
        std::printf("Integer = %d\n", i->value());
    }
    

    And compilation gives me:

    $ g++ test-reference.cpp -O test-reference
    test-reference.cpp: In function ‘int main()’:
    test-reference.cpp:15:18: error: taking address of temporary [-fpermissive]
    
    $ g++ --version
    g++ (Ubuntu/Linaro 4.6.3-1ubuntu3) 4.6.3
    Copyright (C) 2011 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    

    EDIT:

    Using const (as in making foo take a const pointer, and marking value() as const) gives the same error.

  • Alok Save
    Alok Save about 12 years
    you're grabbing the address of a temporary which is very suspicious. No, it is not suspicious.The behavior is well defined,12.2/3 Temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created.
  • Puppy
    Puppy about 12 years
    It's no more dangerous than taking a reference to an rvalue.
  • Mat
    Mat about 12 years
    Ok, didn't mean to mean it was invalid, just (IMO) suspicious.
  • elcuco
    elcuco about 12 years
    @Mat, I need this to be a one liner "without" temporary variables , as this is a temporary variable generated by a DEBUG macro (in my app, its a struct that maintains information about line, file, time, threadID etc).
  • Mat
    Mat about 12 years
    @elcuco: { Integer i(12); foo(&i); }
  • Mat
    Mat about 12 years
    @elcuco: my answer already contains that. The {} add nothing of real value.
  • ams
    ams about 12 years
    GCC is not wrong, it rejected it with error: because it is illegal. -fpermissive is a GCC extension that basically says "yeah, all right, I know what you meant". Extensions are allowed to do whatever non-standard things they like because, well, they're non-standard extensions.
  • Slipp D. Thompson
    Slipp D. Thompson over 9 years
    @Mat The value is that it makes it clear that at a high-level, this is meant as one operation and is only broken down into two for technical reasons, and it limits the scope of the single-letter i var, which could be considered a coding standard taboo if not used in a tightly-confined scope.
  • Arne Vogel
    Arne Vogel almost 9 years
    The standard requires a diagnostic for any ill-formed program unless otherwise specified. A warning is a diagnostic. Even if GCC emitted just a warning without -fpermissive, this would not be a conformance issue.