如果我错过了问题中隐含的一个重要点,我很抱歉,我没有看到它。但是,关于这条中心线:
std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());
这是我认为可以说的:
最后的构造函数调用应该是Packet
, not Packet()
,尽管实际上编译器可能会按原样接受它,并且可能没有任何区别
内部分配new char[size]
使用数组分配器new []
。CPP 参考说明了表达式new [array_n]
:
请注意,由于编译器编码的附加信息(例如数组的大小,因为需要此信息才能正确销毁数组中的对象),因此可能会分配超过 size_of( type ) * array_n 。
现在,外部分配器调用是placement newnew ((void*)(...))
的一个实例,这里描述如下:
void* operator new ( std::size_t, void* ptr );
什么都不做,返回 ptr。
换句话说,调用可能会new []
导致编译器分配比数组严格要求更多的内存,并在额外空间中编码与大小相关的信息。然而,由于placement new“什么都不做”,它不会以任何方式处理或删除额外的信息。
但是,由于使用std::auto_ptr
意味着将使用(而不是)执行释放,因此无法正确释放额外信息,因此可能导致内存泄漏或更糟。delete
delete []
编辑:为避免仅依赖 CPP 参考,C++ 标准 N3337的相关部分如下:
- § 18.6.1.2 规定,仅
delete
应用于释放分配的空间new
,并相应地delete []
用于分配的空间new []
- § 18.6.1.3 明确指出,放置形式
new
不new []
执行任何操作。这意味着两者都不能用于将单个对象空间“转换”为数组空间。
现在也许真正的问题delete []
是,如果仅用于稍后释放空间,则问题中提出的放置新的应用是否有效。也许答案是未定义的(应该被解释为等同于“否”)。