alloca返回的指针的基于索引的访问以及" placement new"

时间:2017-04-24 05:15:58

标签: c++ arrays pointers memory-leaks stack

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来修复它。但我不确定几件事:

  1. 我应该使用new (foo1) Foo[numTargets ];代替new (foo1) Foo();
  2. 我是否应该介绍声明#2以防止任何未来的错误?声明#2在实际中有什么影响?
  3. 声明#1如何帮助防止崩溃?
  4. 其中任何一种情况都有内存泄漏吗?我们是否必须为这两种情况明确地调用析构函数?

1 个答案:

答案 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会好得多。