C++ 使用私有构造函数和自身的静态数组初始化

C++ 使用私有构造函数和自身的静态数组初始化,c++,c++11,initialization,static-initialization,stdarray,C++,C++11,Initialization,Static Initialization,Stdarray,很抱歉,如果标题让人困惑,我找不到一个简单的句子来写。总之,我面临的问题是: // header: class SomeThing { private: SomeThing() {} // <- so users of this class can't come up // with non-initialized instances, but // but the implementation

很抱歉,如果标题让人困惑,我找不到一个简单的句子来写。总之,我面临的问题是:

 // 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];
};
除非我在类中添加一个公共ctor
Something()
,否则我不能使用
std::array
Something
。它适用于老式数组,我可以定义数组,并将其填充到
SomeThing::generateLookupTables()
函数中。显然,类型
std::array
没有构造函数。有没有关于如何让它工作的想法,或者这个概念的更好的结构

================编辑=======

friend std::array方法似乎是个不错的主意,但是:

它也将在其他地方的阵列中使用。我想保证这个类始终对外部用户保持某些不变量。使用这个友好的数组,用户可以意外地创建一个未初始化的
数组


此外,查找表是使用相当复杂的过程生成的,不能按内联方式进行,因为在
std::array SomeThing::lookup\u table\u 0(某些值)

中,由于构造函数是私有的,
std::array
无法使用它

您可以添加
友元类std::数组SomeThing
中进行code>以访问构造函数

另一种方法是使用可用的公共构造函数初始化数组元素:

std::array<SomeThing, 64> SomeThing::lookup_table_0{
    SomeThing(blablabla_ctor_arguments), ..
};
std::array SomeThing::lookup\u table\u 0{
一些东西(喋喋不休的争论)。。
};
编辑:

如果您有移动或复制构造函数,您甚至可以这样做:

std::array<SomeThing, 64> SomeThing::lookup_table_0{ SomeThing() };
std::array SomeThing::lookup_table_0{SomeThing()};
初始化整个数组默认值。

std::array
类试图定义实例时,它显然无权访问
private
默认构造函数。您可以通过添加

friend class std::array<SomeThing, 64>;
friend类std::数组;
对于
某物的定义

解决方案:

std::array<SomeThing, 64> SomeThing::lookup_table_0 {{ }};
尝试使用默认构造函数,因此它的格式不正确。但是,一旦您开始引入初始值设定项,那么
std::array
的默认构造函数就不再起作用了;由于
std::array
是一个聚合,因此会绕过隐式生成的构造函数进行聚合初始化。(如果有任何用户声明的构造函数,那么它将不再是聚合)

具有初始值设定项的版本之所以有效,是因为[dcl.init]/13(n3936):

静态成员的初始值设定项在该成员的类的作用域中


列表初始化的定义在这里将
{}
转换为
{SomeThing()}

Thx,但正如我所见,这将公开私有构造函数。请看我在问题中的编辑。@BuellaGábor:看来我找到了神奇的解决方案:)哇,真聪明。我认为,它实际上创建了一个实例,没有使用垃圾内存对其进行初始化,并创建了该垃圾内存的另外63个副本。这有点愚蠢,但从技术上讲是“有效的”。@BuellaGábor
SomeThing()
调用默认构造函数,没有“非初始化垃圾内存”@MattMcNabb:看看问题中的构造函数:它什么都不做。同时,类实际上有成员变量(问题中没有提到,但它确实有)。该成员没有构造函数,所以在我看来,它只是“垃圾”内存。实际上,我最初想要64个关于垃圾存储的实例,即unitri化的内存。如果你的类是可移动的,考虑使用<代码> STD::vector < /代码>。如果它不可移动,我想当然,只要你使用它,
std::deque
仍然可以工作。我想知道这个类定义是否格式错误,标准容器应该只使用完整的类型实例化。(这个问题只是因为类包含一个来自自身模板的静态成员)Matt:标准容器还没有安装在头中,这个问题是有趣的,因为C样式数组不能简单地被“代码> STD::数组< /代码>取代。我想我还有另一个半解决方案:如果C++在这方面工作与C相同的方式,全局变量,如:::LoopUpTable 0(不在任何函数的堆栈中,所以是全局的)。已初始化为清空内存。因此,如果我创建一个私有构造函数,它只将
一些\u数据设置为零,并使用该值初始化std::array,这基本上是一样的。但这仍然是一种黑客行为。对我来说,这会导致:“错误:缺少成员'std::array::_M_elems'[-Werror=缺少字段初始值设定项]”这与另一种解决方案
lookup_table_0(SomeThing()}
。未初始化和值初始化之间有区别。无论如何,现在我想我会继续使用旧式数组。经过一些思考,我想我可以接受这一个作为解决方案,希望编译器优化程序认识到无论如何都没有工作要做。顺便说一句,我刚刚尝试了这个构造函数:
SomeThing(){std::cout OK。您可以分配一块内存,并在准备就绪时在其上使用placement new,但这会造成更大的混乱。如果您的默认ctor实际上什么都不做,它将被优化掉。
std::array<SomeThing, 64> SomeThing::lookup_table_0 {{ }};
std::array<SomeThing, 64> SomeThing::lookup_table_0;