Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
静态数据成员的类内初始化 < C++ > 代码> static 成员不能在类体中初始化,这些异常有: staticconst的integral type成员可以 static文本类型的constexpr成员必须是_C++_C++11 - Fatal编程技术网

静态数据成员的类内初始化 < C++ > 代码> static 成员不能在类体中初始化,这些异常有: staticconst的integral type成员可以 static文本类型的constexpr成员必须是

静态数据成员的类内初始化 < C++ > 代码> static 成员不能在类体中初始化,这些异常有: staticconst的integral type成员可以 static文本类型的constexpr成员必须是,c++,c++11,C++,C++11,你能解释一下为什么会有这些例外吗 此外,这还包括: 即使在类主体中初始化了const static数据成员,通常也应该在类定义之外定义该成员 这我一点也不明白。这个额外定义的意义是什么 只是想从这里得到一些直觉。为什么类定义中会有初始值设定项 关于const和constepr静态数据成员的两个例外: [class.static.data]/3 [注:在这两种情况下,成员可能出现在常量表达式中。-结束注] 例如,对于初始值设定项,您可以在常量表达式中使用它们,例如 struct s { s

你能解释一下为什么会有这些例外吗

此外,这还包括:

即使在类主体中初始化了
const static
数据成员,通常也应该在类定义之外定义该成员

这我一点也不明白。这个额外定义的意义是什么


只是想从这里得到一些直觉。

为什么类定义中会有初始值设定项

关于
const
constepr
静态数据成员的两个例外:

[class.static.data]/3

[注:在这两种情况下,成员可能出现在常量表达式中。-结束注]

例如,对于初始值设定项,您可以在常量表达式中使用它们,例如

struct s
{
    static std::size_t const len = 10;
    int arr[len];
};
std::size_t const s::len;
如果类定义中没有初始化
len
,编译器就无法在下一行中轻松知道它的值来定义
arr
的长度

有人可能会争论在类定义中允许非
const
、非
constepr
静态数据成员的初始值设定项,但这可能会干扰初始化顺序:

[basic.start.init]/2

显式专用类模板静态数据成员的定义已按顺序初始化。其他类模板静态数据成员(即隐式或显式实例化的专门化)具有无序初始化其他具有静态存储持续时间的非局部变量已按顺序初始化。

也就是说,定义(包括初始值设定项)的顺序很重要。非本地对象的(动态)初始化顺序仅在转换单元内定义,这是必须定义非
const
、非
constepr
静态数据成员的初始化器的另一个原因


这个额外定义的意义是什么


这已经在IMO的评论中得到了回答。您可能希望添加ODR,即,作为具有外部链接的名称,静态数据成员必须(仅)在一个转换单元中定义(如果使用ODR)。由程序员选择此翻译单元。

关键是变量是否将被odr使用。只要它不是,实际上就不需要定义它,因为只要引用变量,就可以粘贴它的值;这是一个定义。在类主体内部有一个声明。由于您可能希望从不同的翻译单元(=cpp文件)访问静态数据成员,因此必须定义每个翻译单元所引用的“位置”,即定义静态成员的单个翻译单元。这和(全局)外部变量是一样的。@DyP:那是错误的。对于类模板,链接器必须已经处理了冗余定义。这里没有区别。编译器不能隐式定义每个全局变量,然后简单地合并它们,这是没有实际原因的,因为在许多情况下已经需要这样做。C++标准(通常)只是在这里不必要地让用户的生命变得不必要。@即使是链接器也可以这样做,对于外部变量IMO来说,这是一样的。你现在必须(根据标准),我猜由于初始化的顺序,它也是有用的。所有错误的原因…与使代码可读不同,它被强制拆分到不同的文件中。@user1656671与C++17一起使用,我们现在有了
inline
变量,这些变量可以在头文件中定义。确实如此。内联帮助。谢谢希望c++20模块将结束所有这些过时的#包括传奇。@user1656671我还没有深入研究模块,但我想它们不会让我们摆脱对象文件和库文件。因此,链接和初始化顺序问题仍然是相关的。我希望模块会使头文件冗余,因此所有与多个包含相关的问题都将消失。我计划在g++将包含在官方版本中的那一刻开始使用模块。当前C++是所有主要语言的背后。在C++中编写非平凡代码需要技巧和奇怪的语法,而其他语法更容易阅读。应该仔细对待初始化顺序,但我认为有一个关于什么是安全的定义。