首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >类定义中的静态数据成员初始化?

类定义中的静态数据成员初始化?
EN

Stack Overflow用户
提问于 2019-03-19 21:20:54
回答 1查看 1.4K关注 0票数 5

我在这里有一个问题,所以,为什么(为什么?)在类中初始化静态变量是不可能的?我所做的

http://eel.is/c++draft/class.static.data#3 如果一个非易失性的非内联静态数据成员是整数或枚举类型的,那么如果程序中使用了odr,那么.仍然应该在名称空间作用域中定义,并且命名空间范围定义不应该包含初始化器。

所以,像这样的例子

代码语言:javascript
运行
复制
struct X {
    static int const n = 7; // should be defined outside the class, 
                            // but it's compiles successfully
};

我看到这个话题https://stackoverflow.com/a/16374286/9780989,就给出了这样一个例子

代码语言:javascript
运行
复制
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++允许在类中定义需要作为对象存储在内存中的实体,则该规则将被打破。

但这不是真的,为什么编译器会解决模板类的静态成员在标头(翻译单元外)中初始化的事实?

代码语言:javascript
运行
复制
// 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;
}

好吧,我试着把我的问题具体化:

  1. 为什么可以在类定义中定义const静态数据成员(如果它没有使用odr,那么它不需要在类之外定义)?
  2. 为什么没有const的静态数据成员可能不能在类定义中定义(请参阅我关于带有静态成员的模板类和Stroustrup关于这个问题的想法(他欺骗我们了吗?)

是的,我看到在C++17中我们允许使用内联,但我对这种情况不太感兴趣。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-19 22:02:54

为什么(为什么?)在类内初始化静态变量是不可能的?

如果静态变量是const,那么在类定义中初始化静态变量是不可能的,不是

但是实际上,如果没有std::size_t const::len--这一行编译也很成功,那么在什么情况下它不应该工作呢?

它的工作是因为变量没有使用odr。请参阅basic.def.odr

变量x,其名称显示为可能计算的表达式e是odr-由e使用,除非

  • X是一个参考..。
  • X是一个非引用类型的变量,可以在常量表达式中使用,并且没有可变的子对象,而e是非易失性限定的非类类型表达式的一组潜在结果的一个元素,其中应用了lvalue-rvalue转换(conv.lval),或.

此外,ODR违规行为是不需要诊断的。对于缺少的定义,这在技术上是正确的。优化可能会删除odr-用途,使它们不会显示为错误。

尝试下面的odr-使用这个变量:

代码语言:javascript
运行
复制
const int *ptr = &X::n;

  1. 为什么可以在类定义中定义const静态数据成员?

不是的。类定义中的声明没有定义非内联const静态数据成员。如果变量是odr使用的,则需要有一个定义(类之外)。

  1. 为什么静态数据成员..。在类定义中可能没有定义(请参阅我关于带有静态成员的模板类和Stroustrup关于这个问题的想法(他欺骗我们了吗?)

Stroustrup关于“复杂的链接器规则”是正确的。当不可能在标头中定义静态变量时,就避免了这种情况。

关于模板的观点是有意义的。无论如何,这些复杂的链接器规则都需要使模板化的静态变量成为可能。并且能够定义甚至非模板的静态变量也有其优点。这些可能是委员会选择允许在C++17中的类定义中定义静态成员的原因。参见:inline静态成员定义。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55250168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档