提问人:nowox 提问时间:4/15/2023 最后编辑:nowox 更新时间:4/16/2023 访问量:125
如何在 C++03 中从初始化列表中初始化数组成员?
How to initialize array members from initialization list in C++03?
问:
以下内容在 C++11 中工作正常,但在 C++03 中不起作用。
struct Foo {
int a, b;
Foo(int a, int b) : a(a), b(b) {}
};
struct Bar {
Foo foos[2];
Bar(int i) :
foos{ {i + 1, i + 2}, {i + 2, i + 3} },
{}
};
int main() {}
C++03 解决方法是什么?
这个问题非常相似,但它并没有真正解决相同的用例。在这里,我想从参数构建子类。Bar
答:
由于没有默认构造函数,因此如果没有 C++11 的列表初始化,则无法初始化数组。Foo
Foo
你的第一个选择是使用一个不到二十年的C++版本,但我想这不是你的选择,否则你不会问这个。
还有其他一些选项,但据我所知,它们都不允许您保持数组完好无损。
使用动态分配
struct BarNew {
Foo* foos;
BarNew(int i) : foos(static_cast<Foo*>(::operator new(sizeof(Foo) * 2)))
{
new (foos + 0) Foo(i+1, i+2);
new (foos + 1) Foo(i+2, i+3);
}
};
这可能看起来很复杂,因为如果不调用构造函数就无法直接使用,而对于数组来说这是不可能的(同样,仅在 C++11 之前)。调用分配而不初始化,就像在 C 中一样。然后,您需要使用 placement-new 来实际构造每个对象。new
::operator new
malloc
用std::vector
struct BarVector {
std::vector<Foo> foos;
BarVector(int i)
{
foos.reserve(2);
foos.push_back(Foo(i+1, i+2));
foos.push_back(Foo(i+2, i+3));
}
};
这是最简单的选项,主要缺点是与数组不同,它也使用动态分配。调用 当然是可选的。reserve
使用数组包装器
template<class T, std::size_t N>
struct ArrayWrapper {
union {
char buffer[sizeof(T)];
unsigned long long dummy;
} storage[N];
T& operator[](std::size_t i) {
return reinterpret_cast<T&>(storage[i]);
}
};
struct BarStruct {
private:
static ArrayWrapper<Foo, 2> foos_init(int i) {
ArrayWrapper<Foo, 2> foos;
foos[0] = Foo(i+1, i+2);
foos[1] = Foo(i+2, i+3);
return foos;
}
public:
ArrayWrapper<Foo, 2> foos;
BarStruct(int i) : foos(foos_init(i))
{
}
};
这是这三个选项中最复杂的,但它的优点是不使用动态分配。可以使它的行为与一个简单的数组非常相似。
此处的结构是泛型的,因此您可以将其用于 以外的类型。它包含一个缓冲区(数组 )来包含每个对象,并使用联合进行对齐,因为 alignas
再次是 C++11 的添加。我不是 100% 确信它在任何情况下都有效;我认为你必须祈祷有足够好的一致性。如果 ,您将浪费一些空间,但如果这让您担心,您可以编写模板专用化。
仅用于提供初始化值。在构造函数之后,您可以像数组一样使用。ArrayWrapper
Foo
char
Foo
unsigned long long
sizeof(T) < sizeof(unsigned long long)
foos_init
foos
我能想到的还有另一种选择,但我没有足够的信心相信它会起作用,或者我的能力来写它,所以我把它作为一个想法。它是选项 2 和 3 的组合,您可以在堆栈上提供存储,就像 一样,但随后使用它来感谢“分配器”功能(第二个模板参数)。这样一来,你就可以在不分配任何内容的情况下获得所有花哨的方法。ArrayWrapper::storage
std::vector
std::vector
std::vector
评论
Foo
int
foos