C++ 放置新位置以获得动态大小

C++ 放置新位置以获得动态大小,c++,memory-management,placement-new,dynamic-sizing,C++,Memory Management,Placement New,Dynamic Sizing,基于这个问题: 下面的方法行吗 { // size calculated. std::auto_ptr<Base> p(new((void*)(new char[size])) Packet()); // Do Stuff } 不,这不起作用:使用任何形式的new构造的对象需要显式销毁,并单独处理内存: void* memory = operator new(size); T* ptr = new(memory) T(args); ... ptr->

基于这个问题:

下面的方法行吗

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

    // Do Stuff
}

不,这不起作用:使用任何形式的
new
构造的对象需要显式销毁,并单独处理内存:

void* memory = operator new(size);
T* ptr = new(memory) T(args);
...
ptr->~T();
operator delete(memory);
还要注意,分配原始内存的方法是而不是类似于
新字符[size]
:这将在内存中构造需要销毁的
char
对象。我意识到,无论是构造还是销毁实际上都不会对内置类型做任何事情,但我很高兴一个实现被允许做一些事情,而且据我所知,不允许跳过这些析构函数


最后,请注意,您还需要构造
int
对象,并且允许实现将某些内容放在结构的明显结尾之后。

否,这不起作用:使用任何形式的
new
构造的对象需要显式销毁,并单独处理内存:

void* memory = operator new(size);
T* ptr = new(memory) T(args);
...
ptr->~T();
operator delete(memory);
还要注意,分配原始内存的方法是而不是类似于
新字符[size]
:这将在内存中构造需要销毁的
char
对象。我意识到,无论是构造还是销毁实际上都不会对内置类型做任何事情,但我很高兴一个实现被允许做一些事情,而且据我所知,不允许跳过这些析构函数


最后,请注意,您还需要构造
int
对象,并且允许实现将某些内容放在结构的明显结尾之后。

如果我错过了问题中隐含的一个要点,并且我没有看到它,我深表歉意。但是,关于这条中心线:

std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());
std::auto_ptr p(新((void*)(新字符[大小])数据包());
我认为可以这样说:

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

  • 内部分配
    newchar[size]
    使用数组分配器
    new[]
    。表达式
    new[array\u n]
    的状态:

  • 请注意,由于编译器编码的附加信息(例如数组的大小,因为需要这些信息才能正确地破坏数组中的对象),因此可能会分配超过(type)*array\n的size_的值

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

    void*新操作符(std::size\u t,void*ptr)不执行任何操作,返回ptr。

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

    但是,由于使用
    std::auto_ptr
    意味着将使用
    delete
    (和not
    delete[]
    )执行解除分配,因此不会正确解除分配额外信息,因此可能会导致内存泄漏或更严重的情况

    编辑:为避免仅依赖CPP参考,以下是相关部分:

    • §18.6.1.2规定只有
      delete
      可用于解除分配
      new
      分配的空间,相应地
      delete[]
      可用于解除分配
      new[]
      分配的空间
    • §18.6.1.3明确规定
      new
      new[]
      的放置形式不执行任何操作。这意味着两者都不能用于将单个对象空间“转换”为阵列空间

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

    如果我错过了问题中隐含的重要一点,并且我没有看到它,我深表歉意。但是,关于这条中心线:

    std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());
    
    std::auto_ptr p(新((void*)(新字符[大小])数据包());
    
    我认为可以这样说:

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

  • 内部分配
    newchar[size]
    使用数组分配器
    new[]
    。表达式
    new[array\u n]
    的状态:

  • 请注意,由于编译器编码的附加信息(例如数组的大小,因为需要这些信息才能正确地破坏数组中的对象),因此可能会分配超过(type)*array\n的size_的值

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

    void*新操作符(std::size\u t,void*ptr)不执行任何操作,返回ptr。

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

    但是,由于使用
    std::auto_ptr
    意味着