提问人:one_two_three 提问时间:9/7/2023 最后编辑:one_two_three 更新时间:9/7/2023 访问量:47
在debug或-O1模式下,将constexpr成员作为引用传递会触发链接器错误,并显示gcc
Passing constexpr member as a reference triggers linker error with gcc in debug or -O1 modes
问:
下面的代码会触发 gcc 'undefined reference Foo::d' 和 'undefined reference Foo::i' 的错误。奇怪的是,只有当我在 -Og 或 -O1 优化模式下编译它时才会发生这种情况,而不是使用 -O2 或 -O3 编译它。此外,如果我作为参数传递,反之亦然(参见最后的调用)——它不会触发错误。constexpr double
int&
#include <stdio.h>
class Foo
{
public:
static constexpr double d = 10.0;
static constexpr int i = 10;
}; //class Foo
void print_double_ref(const double& v)
{
printf("v = %g\n", v);
}
void print_int_ref(const int& n)
{
printf("n = %i\n", n);
}
int main()
{
Foo a;
//This part triggers link error with -Og, -O1
//No error with -O2, -O3
print_double_ref(a.d);
print_int_ref(a.i);
//This part does not trigger link error with -Og, -O1
print_int_ref(a.d);
print_double_ref(a.i);
}
我知道,这个问题在某种程度上与声明函数参数和作为引用有关。问题是:print_double_ref
print_int_ref
- 为什么仅在 -Og 和 -O1 模式下出现链接错误?
- 为什么作为参数传递(或作为参数传递)不会产生错误?
constexpr double
const int&
constexpr int
const double&
更新:我知道对于成员来说,应该在类外初始化它们。但是,必须在声明时定义变量。那么为什么允许编译这样的结构呢?static const
constexpr
答:
2赞
n. m. could be an AI
9/7/2023
#1
该程序不包含 和 的定义(仅包含声明),并且这些东西正在使用 ODR。因此,该行为是未定义的。Foo::i
Foo::d
传递给错误的引用参数类型不会触发绑定引用,而是创建临时参数,然后将引用绑定到该参数。因此,在这种情况下不使用ODR。
评论
1赞
one_two_three
9/7/2023
我理解它是为了,但不是 - 没有办法拆分声明和定义。static const double
static constexpr double
constexpr
1赞
n. m. could be an AI
9/7/2023
@one_two_three godbolt.org/z/6Yfox436c
评论
static inline ...
static constexpr int i = 10;
inline