使用constexpr静态成员变量的奇怪行为

R S*_*ahu 11 c++ c++11

这是对未定义的静态constexpr char [] []的引用的后续问题.

以下程序构建并运行良好.

#include <iostream>

struct A {
   constexpr static char dict[] = "test";

   void print() {
      std::cout << A::dict[0] << std::endl;
   }
};

int main() {
   A a;
   a.print();
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我A::print()改为:

   void print() {
      std::cout << A::dict << std::endl;
   }
Run Code Online (Sandbox Code Playgroud)

我在g ++ 4.8.2中收到以下链接器错误.

/tmp/cczmF84A.o: In function `A::print()':
socc.cc:(.text._ZN1A5printEv[_ZN1A5printEv]+0xd): undefined reference to `A::dict'
collect2: error: ld returned 1 exit status

可以通过添加一行来解决链接器错误:

constexpr char A::dict[];
Run Code Online (Sandbox Code Playgroud)

在课堂定义之外.

但是,我不清楚为什么使用数组的一个成员在使用数组时不会导致链接器错误导致链接器错误.

小智 7

该标准不需要任何诊断,因为无法提供需要的定义.

3.2一个定义规则[basic.def.odr]

4每个程序应包含该程序中每个非内联函数或变量的一个定义; 无需诊断.[...]

这意味着允许实现优化对这些变量的访问,这就是你在GCC的第一种情况下发生的事情.

GCC和clang都决定他们更喜欢一致的用户体验,其中关于缺失定义的错误消息不依赖于优化级别.通常,这意味着任何缺少的定义都会导致错误消息.但是,在这种情况下,GCC即使在进行一些最小化优化-O0,也避免了错误.

但该程序无论如何都是错误的,因为即使A::dict[0]是ODR使用:

3.2一个定义规则[basic.def.odr]

3 除非应用左值到右值转换(4.1)以产生不调用任何非平凡函数的常量表达式(5.19),否则x其名称显示为潜在评估表达式的变量将被ex使用.如果是对象,是表达式的潜在结果集合的元素,其中左值到右值的转换(4.1)应用于或者是丢弃值表达式(第5节).[...]exxxexeee

使用A::dict不涉及lvalue-to-rvalue转换,它涉及数组到指针的转换,因此异常不适用.

  • 这可能会受益于关于为什么`A :: dict [0]`是odr-use的讨论. (2认同)