// header: class SomeThing { private: SomeThing() {} // <- so users of this class can't come up // with non-initialized instances,but // but the implementation can. int some_data; // <- a few bytes of memory,the default // constructor SomeThing() doesn't initialize it public: SomeThing(blablabla ctor arguments); static SomeThing getThatThing(blablabla arguments); static void generateLookupTables(); private: // declarations of lookup tables static std::array<SomeThing,64> lookup_table_0; static SomeThing lookup_table_1[64]; };
getThatThing函数用于从查找表返回实例.
// in the implementation file - definitions of lookup tables std::array<SomeThing,64> SomeThing::lookup_table_0; // error SomeThing Something::lookup_table_1[64]; // <- works fine
我只是不能使用某事的std :: array,除非我在类中添加一个公共ctor SomeThing().它适用于旧式数组,我可以定义数组,并在SomeThing :: generateLookupTables()函数中填充它.显然类型为std :: array< SomeThing,64>没有构造函数.关于如何使其工作的任何想法,或者对于这个概念可能是更好的结构?
=============编辑=======
朋友std :: array< SomeThing,64>方法似乎是个好主意,但是:
它也将在其他地方的数组中使用.我想保证这个类始终保持某些不变量对外部用户.使用这个友好的数组,用户可能会意外地创建一个未初始化的SomeThing数组.
此外,查找表是使用相当复杂的过程生成的,不能按内联完成,如std :: array< SomeThing,64> SomeThing :: lookup_table_0(某个值)
解决方法
std::array<SomeThing,64> SomeThing::lookup_table_0 {{ }};
注意:正如here所解释的那样,{{}}需要在gcc中对std :: array进行值初始化而不发出警告. = {}和{}是正确的,但gcc仍然会发出警告.
解决方案的关键是必须存在某种形式的初始化程序.
首先进行术语检查:所有对象都在C中初始化.有三种形式,默认值,值和零.没有“未初始化”的对象;没有显式初始化程序的对象称为默认初始化.在某些情况下,这意味着对象的成员变量可能是不确定的(“垃圾”).
no-initializer版本有什么问题?首先,std :: array< SomeThing,64>的构造函数.被定义为删除,因为声明std :: array< SomeThing,64> X;将是不正确的(由于缺少SomeThing的可访问的默认构造函数,当然).
这意味着任何尝试使用std :: array< SomeThing,64>的默认构造函数的代码.反过来又形成了不良形象.定义:
std::array<SomeThing,64> SomeThing::lookup_table_0;
确实尝试使用默认构造函数,因此它是错误的.但是一旦你开始介绍初始化器,那么std :: array的默认构造函数就不再存在了;由于std :: array是一个聚合,因此聚合初始化会绕过隐式生成的构造函数. (如果有任何用户声明的构造函数,那么它将不再是聚合).
带有初始化程序的版本因[dcl.init] / 13(n3936)而起作用:
An initializer for a static member is in the scope of the member’s class
列表初始化的定义在此处将{}转换为{SomeThing()}.