【发布时间】:2014-08-31 04:45:20
【问题描述】:
C++ 不允许类包含不可默认构造的项目数组:
class Gordian {
public:
int member;
Gordian(int must_have_variable) : member(must_have_variable) {}
};
class Knot {
Gordian* pointer_array[8]; // Sure, this works.
Gordian inlined_array[8]; // Won't compile. Can't be initialized.
};
即使是 C++ 初学者也知道,该语言保证在构造类时初始化所有非 POD 成员。而且它不信任用户初始化构造函数中的所有内容 - 必须在构造函数的主体开始之前向所有成员的构造函数提供有效参数。
总的来说,就我而言,这是一个好主意,但我遇到过这样一种情况,如果我实际上可以拥有一组非默认可构造对象,那会容易得多。
显而易见的解决方案:拥有一个指向对象的指针数组。在我的情况下,这不是最佳选择,因为我使用的是共享内存。这将迫使我从已经竞争的资源(即共享内存)中进行额外分配。我希望在对象中内联数组的全部原因是减少分配的数量。
在这种情况下,我愿意使用 hack,即使是丑陋的,只要它有效。我正在考虑的一种可能的技巧是:
class Knot {
public:
struct dummy { char padding[sizeof(Gordian)]; };
dummy inlined_array[8];
Gordian* get(int index) {
return reinterpret_cast<Gordian*>(&inlined_array[index]);
}
Knot() {
for (int x = 0; x != 8; x++) {
new (get(x)) Gordian(x*x);
}
}
};
当然,它可以编译,但我并不是一个经验丰富的 C++ 程序员。也就是说,我不可能少相信我的黑客。那么问题来了:
1) 我想出的破解方法看起来可行吗?有哪些问题? (我主要关心新版本 GCC 上的 C++0x)。
2) 有没有更好的方法来内联类中的非默认可构造对象数组?
【问题讨论】:
-
代码合法。但是,我认为将非 POD C++ 对象放在共享内存中是一个糟糕的设计。
-
我认为您当前的解决方案还可以。您可能希望将
vector与自定义分配器一起使用,该分配器将从您准备的缓冲区分配内存,但如果您不想在此缓冲区中预分配任何额外内存,则这种方法 afaik 不起作用。 -
“语言保证在构造类时初始化所有成员”的说法是不正确的。 C++ 不保证 POD 类型(整数、C 风格结构等)的初始化。
-
@Cantos:哦,你 :) 但是,是的,当我在做陈述时,我不妨正确地做。编辑修复。
-
(多年后)旁注:“hack”很可能是 C++11 及更高版本中未定义的行为。 std::aligned_storage - cppreference.com 。另见c++ - Initialize array of non default constructible objects of template argument length - Stack Overflow
标签: c++ constructor