我在这里有一个问题,所以,为什么(为什么?)在类中初始化静态变量是不可能的?我所做的
http://eel.is/c++draft/class.static.data#3 如果一个非易失性的非内联静态数据成员是整数或枚举类型的,那么如果程序中使用了odr,那么.仍然应该在名称空间作用域中定义,并且命名空间范围定义不应该包含初始化器。
所以,像这样的例子
struct X {
static int const n = 7; // should be defined outside the class,
// but it's compiles successfully
};
我看到这个话题https://stackoverflow.com/a/16374286/9780989,就给出了这样一个例子
struct s
{
static std::size_t const len = 10;
int arr[len];
};
std::size_t const s::len;
有话说,-
“如果类定义中没有初始化len,编译器很难在下一行中知道它的值,从而定义arr的长度。”
但是实际上,如果没有std::size_t const::len--这行编译也很成功,那么在什么情况下它不应该工作呢?https://gcc.godbolt.org/z/OMKzEO
所以我们更进一步,为什么我们不能初始化类中的静态成员,const限定符允许这样做,为什么没有我们不能这样做呢?允许在类内初始化的const是做什么的?
您可能会说,我们无法在类内初始化静态成员,因为ODR和Stroustrup的意思是:
类通常在头文件中声明,而头文件通常包含在许多翻译单元中。然而,为了避免复杂的链接器规则,C++要求每个对象都有一个唯一的定义。如果C++允许在类中定义需要作为对象存储在内存中的实体,则该规则将被打破。
但这不是真的,为什么编译器会解决模板类的静态成员在标头(翻译单元外)中初始化的事实?
// templates are completely pushed into headers
template<typename T>
struct X {
static int val;
};
// here the static member of the template class is initialized in the header
template<typename T>
int X<T>::val = 0;
int main() {
X<int> x;
}
好吧,我试着把我的问题具体化:
是的,我看到在C++17中我们允许使用内联,但我对这种情况不太感兴趣。
发布于 2019-03-19 14:02:54
为什么(为什么?)在类内初始化静态变量是不可能的?
如果静态变量是const,那么在类定义中初始化静态变量是不可能的,不是。
但是实际上,如果没有std::size_t const::len--这一行编译也很成功,那么在什么情况下它不应该工作呢?
它的工作是因为变量没有使用odr。请参阅basic.def.odr
变量x,其名称显示为可能计算的表达式e是odr-由e使用,除非
此外,ODR违规行为是不需要诊断的。对于缺少的定义,这在技术上是正确的。优化可能会删除odr-用途,使它们不会显示为错误。
尝试下面的odr-使用这个变量:
const int *ptr = &X::n;
不是的。类定义中的声明没有定义非内联const静态数据成员。如果变量是odr使用的,则需要有一个定义(类之外)。
Stroustrup关于“复杂的链接器规则”是正确的。当不可能在标头中定义静态变量时,就避免了这种情况。
关于模板的观点是有意义的。无论如何,这些复杂的链接器规则都需要使模板化的静态变量成为可能。并且能够定义甚至非模板的静态变量也有其优点。这些可能是委员会选择允许在C++17中的类定义中定义静态成员的原因。参见:inline
静态成员定义。
https://stackoverflow.com/questions/55250168
复制相似问题