"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 编译。
- 在
Foo
之外添加行 constexpr const int Foo::OUT_OF_BOUNDS;
让 GCC 编译得很好。 VS2015还是报错
- 删除
constexpr
并从定义中拆分声明修复了警告,但为什么我必须这样做?
OUT_OF_BOUNDS 不是本地的,也不是临时的,对吧?它在 class 定义中定义和声明时没有地址吗?
当您在函数中使用 constexpr
时,会创建一个临时本地实例。您可以尝试在静态成员 OUT_OF_BOUNDS
的声明中省略 constexpr
和 static
,这样您就有了一个 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++11,C++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 收到的警告似乎是一个错误。
我有这个 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 编译。
- 在
Foo
之外添加行constexpr const int Foo::OUT_OF_BOUNDS;
让 GCC 编译得很好。 VS2015还是报错 - 删除
constexpr
并从定义中拆分声明修复了警告,但为什么我必须这样做?
OUT_OF_BOUNDS 不是本地的,也不是临时的,对吧?它在 class 定义中定义和声明时没有地址吗?
当您在函数中使用 constexpr
时,会创建一个临时本地实例。您可以尝试在静态成员 OUT_OF_BOUNDS
的声明中省略 constexpr
和 static
,这样您就有了一个 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++11,C++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 收到的警告似乎是一个错误。