Home > Blockchain >  "warning C4172: returning address of local variable or temporary" when returning reference
"warning C4172: returning address of local variable or temporary" when returning reference

Time:12-15

I have this class with a function that returns a value. For complicated reasons, the value needs to be returned as a const reference.

(minimal working example contains an int array, real code has more complex objects, hence the reference)

class Foo
{
public:
    static constexpr const int OUT_OF_BOUNDS_VALUE = -9999;
    const int& ret(int i) const { return i < 0 || i > 4 ? OUT_OF_BOUNDS_VALUE : test[i]; }

private:
    int test[5] = {0, 1, 2, 3, 4};
};

This gives me warning C4172: returning address of local variable or temporary in VS2015 and it doesn't even compile with GCC.

  • Adding the line constexpr const int Foo::OUT_OF_BOUNDS; outside of Foo lets GCC compile just fine. VS2015 still gives the warning.
  • Removing constexpr and splitting the declaration from the definition fixes the warning, but why should I have to do that?

OUT_OF_BOUNDS isn't local, and it isn't temporary, right? Does it not have an address when it is defined and declared inside of the class definition?

See the warning live: https://godbolt.org/z/fv397b9rr

CodePudding user response:

What happens when you use the constexpr in your function is that a temporary local instance is created. You could try to leave out constexpr and static in the declaration of your static member OUT_OF_BOUNDS so you have a const object / instance you can get a reference of.

EDIT: If you must have a static member, declare it const static int and put in the definition const int Foo::OUT_OF_BOUNDS = -1; in an appropriate place.

CodePudding user response:

The problem is that in C 11, we have to add a corresponding definition for a static constexpr declaration of a class' data member. This is explained in more detail below:

C 11

class Foo
{
public:
    static constexpr const int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DECLARATION IN C  11 and C  14
    //other members here
};

In the above code snippet(which is for C 11,C 14), we have a declaration of the static data member OUT_OF_BOUNDS_VALUE inside the class. And so, in exactly one translation unit we have to provide a corresponding definition. Otherwise you'll get a linker error which can be seen here.

That is, in exactly one translation unit we should write:

constexpr const int Foo::OUT_OF_BOUNDS;//note no initializer

C 17

class Foo
{
public:
    static constexpr const int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DEFINITION IN C  17
    //other members here
};

In the above code snippet(which is for C 17) we have a definition of the static data member OUT_OF_BOUNDS_VALUE inside the class. So since C 17, we don't have to provide the definition of OUT_OF_BOUNDS_VALUE anywhere else since we already have a definition for it inside the class.


The warning that you're getting with MSVC seems to be a bug.

CodePudding user response:

test[i] is an int, you're binding it to a reference to const int in the return statement. No?

  • Related