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];
};
除非我在类中添加一个公共ctorSomething()
,否则我不能使用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áborSomeThing()
调用默认构造函数,没有“非初始化垃圾内存”@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;