"warning C4172: returning address of local variable or temporary" 返回对静态成员的引用时

"warning C4172: returning address of local variable or temporary" when returning reference to static member

我有这个 class 的函数 returns 一个值。由于复杂的原因,该值需要作为 const 引用返回。

(最小工作示例包含一个 int 数组,实际代码具有更复杂的对象,因此参考)

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};
};

这给了我 warning C4172: returning address of local variable or temporary 在 VS2015 中,它甚至不能用 GCC 编译。

OUT_OF_BOUNDS 不是本地的,也不是临时的,对吧?它在 class 定义中定义和声明时没有地址吗?

实时查看警告:https://godbolt.org/z/fv397b9rr

当您在函数中使用 constexpr 时,会创建一个临时本地实例。您可以尝试在静态成员 OUT_OF_BOUNDS 的声明中省略 constexprstatic,这样您就有了一个 const 对象/实例,您可以获取对它的引用。

编辑: 如果你必须有一个静态成员,声明它 const static int 并把定义 const int Foo::OUT_OF_BOUNDS = -1; 放在适当的地方。

test[i] 是一个 int,您将其绑定到 return 语句中对 const int 的引用。没有?

问题是在C++11中,我们必须为static添加相应的定义 class' 数据成员的 constexpr 声明 。这在下面有更详细的解释:

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
};

在上面的代码片段中(针对C++11C++14),我们有一个[= class 内部的静态数据成员 OUT_OF_BOUNDS_VALUE 的 35=] 声明。因此,在正好一个翻译单元中,我们必须提供相应的定义。否则你会得到一个 链接器错误 可以看到 here.

也就是说,在一个翻译单元中我们应该这样写:

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
};

在上面的代码片段中(针对 C++17)我们有一个静态数据成员 定义 OUT_OF_BOUNDS_VALUE里面的class。因此,从 C++17 开始,我们不必在其他任何地方提供 OUT_OF_BOUNDS_VALUE 定义,因为我们已经在 class 中为它定义了它。


您使用 MSVC 收到的警告似乎是一个错误。