一、介绍
一般来说,使用new申请空间时,是从系统的“堆”(heap)中分配空间,申请所得空间的位置是随机的。但是,在某些特殊情况下,可能需要在已分配的特定内存创建对象(比如内存池),这就是所谓的“定位放置new”(placement new)操作。
定位放置new操作的语法形式不同于普通的new操作。例如,一般都用如下语句A* p=new A;申请空间,而定位放置new操作则使用如下语句:
A* p = new (ptr)A
来申请空间,其中ptr就是程序员指定的内存首地址。使用之后,要显示的调用对象的析构函数来释放内存。
二、实例
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A's constructor" << endl;
}
~A()
{
cout << "A's destructor" << endl;
}
void show()
{
cout << "num:" << num << endl;
}
private:
int num;
};
int main()
{
char mem[100];
mem[0] = 'A';
mem[1] = '\0';
mem[2] = '\0';
mem[3] = '\0';
cout << (void*)mem << endl;
A* p = new (mem)A; // 在已分配的内存上创建对象A
cout << p << endl;
p->show();
p->~A();
system("pause");
return 0;
}
打印
1)用定位放置new操作,既可以在栈(stack)上生成对象,也可以在堆(heap)上生成对象。如本例就是在栈上生成一个对象。
(2)使用语句A* p=new (mem) A;定位生成对象时,指针p和数组名mem指向同一片存储区。所以,与其说定位放置new操作是申请空间,还不如说是利用已经请好的空间,真正的申请空间的工作是在此之前完成的。
(3)使用语句A *p=new (mem) A;定位生成对象时,会自动调用类A的构造函数,但是由于对象的空间不会自动释放(对象实际上是借用别人的空间),所以必须显示的调用类的析构函数,如本例中的p->~A()。
参考: