[指南]:本文主要介绍如何使新运算符不分配内存,而仅构造。
问题c ++++中的new运算符通常完成两项任务,分配内存并调用相应的构造函数。
请问:如何使新运算符不分配内存而仅调用构造函数?这种用法有什么用?无需分配内存,仅调用构造函数即可实现Placementnew,placementnew的含义。
void * operatornew(size_t,void * p)throw(){returnp;} placementnew的实现会忽略size_t参数,而仅返回第二个参数。
结果是允许用户将对象放在特定的位置,以达到调用构造函数的效果。
用法如下:#include#includeclassTest {public:Test(){std :: cout〜Test();}}输出:ConstructorConstructorDestructor与其他普通new函数之间的区别在于,它在方括号中具有另一个参数。
例如:Widget * p = newWidget; --------- // ordinarynewpi = new(ptr)int; pi = new(ptr)int; // placementnew括号中的参数ptr是一个指针,该指针指向到内存缓冲区,placementnew将在此缓冲区上分配一个对象。
Placementnew的返回值是所构造对象的地址(例如,括号中传递的参数)。
Placementnew主要适用于:在需要非常长时间的应用程序中,因为确定了为这些程序分配的时间;长时间运行而不会被中断的程序;以及垃圾收集器(garbagecollector)的实现。
new,operatornew和placementnew之间的区别是新的:它不能重载,并且其行为始终是一致的。
它首先调用operatornew分配内存,然后调用构造函数初始化该内存。
operatornew:要实现不同的内存分配行为,应该重载operatornew而不是new。
delete与operatordelete类似。
Delete首先调用对象的析构函数,然后调用operatordelete释放使用的内存。
PlacementNew:只是operatornew重载的一个版本。
它不分配内存,而是返回一个指向已分配内存的特定段的指针。
因此,不能删除它,但是需要调用对象的析构函数。
new运算符的执行过程调用operatornew来分配内存;调用构造函数生成一个类对象;返回相应的指针。
PlacementNew允许您在已分配的内存(堆栈或堆)中构造一个新对象。
原型中的void * p实际上指向分配的内存缓冲区的第一个地址。
存在Placementnew的原因是使用Placementnew来解决缓冲区问题。
描述:使用new分配的数组缓冲区时,由于调用了默认构造函数,因此执行效率不好。
如果没有默认构造函数,则会发生编译时错误。
如果要在预分配的内存上创建对象,则无法使用默认的new运算符。
要解决此问题,可以使用placementnew结构。
它允许您将一个新对象构造到预分配的内存中。
增加时空效率的问题。
使用new运算符分配内存需要在堆中找到足够大的剩余空间。
显然,此操作速度非常慢,并且可能存在无法分配内存(空间不足)的异常。
placementnew可以解决此问题。
我们在预先准备的内存缓冲区中构造对象。
无需查找内存。
内存分配的时间是恒定的;并且在程序中间不会有内存不足的例外。
因此,placementnew非常适合那些需要相对较长时间并且不想长时间运行而被打断的应用程序。
使用步骤在许多情况下,placementnew的用法与其他普通new不同。
这是使用它的步骤。
第一步是以三种方式预先分配高速缓存:为了确保placementnew所使用的缓冲区的memoryalignmen(内存队列)已正确准备,请使用普通的new来分配它:在堆上分配classTask;在堆上分配classTask。
char * buff = new [sizeof(Task)]; //分配内存(请注意,不是针对每种对象类型正确地安排了自动或静态内存,因此您将无法将它们用作placementnew。
)在堆栈上分配classTask; charbuf [N * sizeof(Task)]; //还有另一种分配内存的方法,即直接通过地址使用它。
(必须是一个有意义的地址)void * buf = reinterpret_cast(0xF00F);步骤2:对象分配在分配的缓冲区中调用placementnew来构造对象。
Task * ptask = new(buf)Task步骤3:以通常的方式使用分配的对象:ptask-> memberfunction(); ptask-> member; // ...步骤4:使用后销毁对象完成此对象后,您必须