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]
的状态:new((void*)(…)
,是placement new的一个实例,描述如下:
void*新操作符(std::size\u t,void*ptr)代码>不执行任何操作,返回ptr。
换句话说,调用new[]
可能会导致编译器分配比数组严格要求的内存更多的内存,并在额外空间中编码大小相关信息。但是,由于placement new“不做任何事情”,因此它不会以任何方式处理或删除额外信息
但是,由于使用std::auto_ptr
意味着将使用delete
(和notdelete[]
)执行解除分配,因此不会正确解除分配额外信息,因此可能会导致内存泄漏或更严重的情况
编辑:为避免仅依赖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
意味着