【问题标题】:Placement new to get dynamic sizeing新的展示位置以获得动态大小
【发布时间】:2012-03-15 05:16:12
【问题描述】:

基于这个问题:Variable size type allocation

以下是否有效?

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

    // Do Stuff
}

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

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

【问题讨论】:

  • 我觉得this question 很相关。
  • 对不起,如果我在这里误解了一些东西。但是你基本上是在问是否可以使用delete(而不是delete [])来释放使用new []分配的内存?

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


【解决方案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 对象,并且允许实现在结构明显结束后放置一些内容。

【讨论】:

    【解决方案2】:

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

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

    这是我认为可以说的:

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

    2. 内部分配new char[size] 使用数组分配器new []CPP reference 声明了表达式 new [array_n]

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

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

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

    换句话说,可能发生调用new []会导致编译器分配比数组严格要求更多的内存编码额外空间中的尺寸相关信息。然而,由于placement new“什么都不做”,它不会以任何方式处理或删除额外的信息。

    但是,由于使用std::auto_ptr 意味着解除分配 将使用delete(并且不是 delete [])执行,额外信息将没有正确释放,因此可能导致内存泄漏或更糟。

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

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

    现在也许真正的问题是,如果以后只使用delete [] 来释放空间,那么问题中提出的placement new 应用是否有效。也许答案是不确定的(应该被解释为等同于“否”)。

    【讨论】:

    • 实际上new Packetnew Packet() 都是有效的(尽管含义略有不同(第二个将零初始化结构第一个将默认初始化结构))所以它没有错或不好。
    • 请不要使用 cpprefeence 作为来源。它包含了很多错误。免费使用它作为起点,但是当您开始引用某些东西作为权威来源时,它应该是标准。此外,添加的额外空间不会影响返回的内存,因为它不是返回的内存的一部分(标准有某些不违反的保证,额外的空间不是其中的一部分,也不影响这些保证)。在此处获取标准副本:stackoverflow.com/a/4653479/14065
    • @Loki Astari 当然我同意new [] 分配的额外空间返回。但这不正是问题所在吗?这就是为什么new [] 分配的空间必须使用delete [] 释放,不是吗?因为否则在释放期间不会考虑该空间。
    • @Loki Astari 我添加了对 C++ 标准的引用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-06
    相关资源
    最近更新 更多