基于这个问题: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];
}
答案 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());
我认为可以这么说:
最后的构造函数调用应该是Packet
,而不是Packet()
,尽管在实践中编译器可能会按原样接受它,并且它可能没有任何区别
内部分配new char[size]
使用数组分配器new []
。关于表达式new [array_n]
:
请注意,由于编译器编码的附加信息(例如数组的大小,因为需要此信息才能正确破坏数组中的对象),因此可能会分配大于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的相关部分如下:
delete
用于解除分配new
分配的空间,并相应地delete []
分配new []
分配的空间new
和new []
的展示位置不会执行任何操作。这意味着两者都不能用于将单个对象空间“转换”为数组空间。现在也许真实问题是,如果以后仅使用delete []
来释放空间,那么问题中提出的新位置的应用是否有效。也许答案是未定义的(应该被解释为等同于“否”)。