传递 constexpr 成员作为引用会在调试或 -O1 模式下触发 gcc 的链接器错误

问题描述 投票:0回答:1

下面的代码会触发 gcc '未定义的引用 Foo::d' 和 '未定义的引用 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
的参数作为引用有关。问题是:

  1. 为什么仅在 -Og 和 -O1 模式下出现链接错误?
  2. 为什么将
    constexpr double
    作为
    const int&
    的参数传递(或
    constexpr int
    作为
    const double&
    的参数)不会产生错误?
c++ reference pass-by-reference constexpr
1个回答
0
投票

该程序不包含

Foo::i
Foo::d
的定义(仅声明),并且这些内容正在被 ODR 使用。因此,该行为是未定义的。

传递给错误的引用参数类型不会触发绑定引用,而是创建一个临时对象,然后将引用绑定到该临时对象。因此,在这种情况下不使用 ODR。

© www.soinside.com 2019 - 2024. All rights reserved.