Foo* foo1 = static_cast<Foo*>( alloca( sizeof( Foo ) * numTargets ) );
new (foo1) Foo(); // Statement 1: Calls constructor Foo()
Foo** foo2 = static_cast<Foo**>( alloca( sizeof( Foo* ) * numTargets ) );
new (foo2) Foo*(); // Statement 2: Doesn't calls constructor Foo()
在我目前的项目中,声明1&amp; 2不存在。
当尝试填充foo1[i]
中的值时,没有声明#1导致崩溃(一个错误)。我通过引入声明#1来修复它。但我不确定几件事:
new (foo1) Foo[numTargets ];
代替new (foo1) Foo();
答案 0 :(得分:2)
我应该使用
吗?new (foo1) Foo[numTargets ];
代替new (foo1) Foo();
没有。数组placement-new在分配中需要额外的内存来存储有关数组的详细信息。 C ++标准声明未指定额外内存量,这意味着它取决于C ++编译器和/或标准库实现。
您应该循环遍历数组并放置新的每个对象:
for (size_t i = 0; i < numTargets; ++i) {
new (foo1 + i) Foo();
}
我是否应该介绍声明#2以防止任何未来的错误?声明#2在现实中有什么影响?
所有这一切都将foo2[0]
设置为等于nullptr
。
声明#1如何帮助防止崩溃?
使用尚未构造的对象是未定义的行为。崩溃是一种可能的结果,但在构造指向对象之前以任何方式解除引用foo1
都可能导致任何行为。
其中任何一种情况都有内存泄漏吗?我们是否必须为这两种情况明确地调用析构函数?
除了你有效地拥有一个指针数组之外,第二个没有内存泄漏。如果您在此数组中分配了任何元素但没有delete
该元素,那么您可能会泄漏分配(取决于此数组是否拥有分配)。
您必须在第一种情况下显式调用析构函数,这样可以防止任何内存Foo
对象可能动态分配的任何内存泄漏。
for (size_t i = 0; i < numTargets; ++i) {
foo1[i].~Foo();
}
老实说,你在这里使用std::vector
会好得多。