放置新的以获得动态大小调整

时间:2012-03-15 05:16:13

标签: c++ memory-management placement-new dynamic-sizing

基于这个问题:Variable size type allocation

以下是否有效?

{
    // size calculated.
    std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());

    // Do Stuff
}

数据包是POD结构,其中最后一个成员是数组。这个想法是允许一个动态大小的数组(就像我们以前在C中所做的那样)

struct Packet
{
    // STUFF
    int  data[1];
}

2 个答案:

答案 0 :(得分:1)

不,这不起作用:使用除new之外的任何形式的std::nothrow构建的额外参数构建的对象需要明确销毁并且内存已分别处理:

void* memory = operator new(size);
T* ptr = new(memory) T(args);
...
ptr->~T();
operator delete(memory);

另请注意,分配原始内存的方式是而不是类似于new char[size]:这会在内存中构造需要销毁的char个对象。我意识到构建和破坏实际上都没有对内置类型做任何事情,但是我实际上允许执行某些操作,并且据我所知,没有权限跳过这些析构函数。

最后,请注意您还需要构造int个对象,并且允许实现在结构的明显结束之后放置一些东西。

答案 1 :(得分:0)

如果我错过了一个隐含在问题中的重要观点而且我没有看到它,我道歉。但是,关于这条中心线:

std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());

我认为可以这么说:

  1. 最后的构造函数调用应该是Packet,而不是Packet(),尽管在实践中编译器可能会按原样接受它,并且它可能没有任何区别

    < / LI>
  2. 内部分配new char[size]使用数组分配器new []。关于表达式new [array_n]

  3. CPP reference个州
      

    请注意,由于编译器编码的附加信息(例如数组的大小,因为需要此信息才能正确破坏数组中的对象),因此可能会分配大于size_of(type)* array_n。

    现在,外部分配器调用new ((void*)(...)) placement new 的一个实例,其描述如下here

      

    void* operator new ( std::size_t, void* ptr ); 什么都不做,返回ptr。

    换句话说,可能发生new []的调用会导致编译器分配比数组严格要求更多的内存 >在额外空间中编码与大小相关的信息。但是,由于放置新的“无”,它不会以任何方式处理或删除额外信息。

    但是,由于std::auto_ptr的使用意味着取消分配将使用delete(和 delete []执行),额外信息将无法正确释放,因此可能导致内存泄漏或更糟。

    修改:为避免仅依赖CPP参考,C++ Standard N3337的相关部分如下:

    • §18.6.1.2规定只有delete用于解除分配new分配的空间,并相应地delete []分配new []分配的空间
    • §18.6.1.3明确声明newnew []的展示位置不会执行任何操作。这意味着两者都不能用于将单个对象空间“转换”为数组空间。

    现在也许真实问题是,如果以后仅使用delete []来释放空间,那么问题中提出的新位置的应用是否有效。也许答案是未定义的(应该被解释为等同于“否”)。