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 члены инициализируются при создании класса. И он не доверяет пользователю инициализировать все в конструкторе - нужно предоставить действительные аргументы конструкторам всех членов до того, как тело конструктора даже запустится.
В общем, это хорошая идея, насколько я понимаю, но я сталкивался с ситуацией, когда было бы намного проще, если бы я мог на самом деле иметь массив конструируемых объектов, отличных от заданных по умолчанию.
Очевидное решение: иметь массив указателей на объекты. Это не оптимально в моем случае, так как я использую общую память. Это заставило бы меня сделать дополнительное выделение из уже конкурирующего ресурса (то есть разделяемой памяти). Единственная причина, по которой я хочу, чтобы массив был встроен в объект, заключается в уменьшении количества выделений.
Это ситуация, когда я хотел бы использовать хак, даже уродливый, при условии, что он работает. Один из возможных способов взлома:
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) Кажется ли работоспособным взлом, который я придумал? Какие проблемы? (В основном меня интересует C ++ 0x в новых версиях GCC).
2) Есть ли лучший способ встроить в массив массив конструируемых объектов, отличных от заданных по умолчанию?