#include <iostream>
#include <cstring>
using namespace std;
class People
{
private:
char *name;
int age;
public:
People(){name=0;};
People(char *na, int ag=18): age(ag)
{
int sz = strlen(na)+1;
name = new char[sz];
strcpy_s(name, sz, na);
}
~People()
{
cout<<name<<" has been successfully deleted!"<<endl;
delete[] name;
}
void show()
{
cout<<name<<endl;
}
};
int main()
{
if (1)
{
//char buffer[20]; // 采用这一句,则无需delete[] buffer;其他均一样
char *buffer= new char[20];
People *p1 = new(buffer) People("chen"); // new 定位符将对象*p1定位到地址buffer上
People *p2 = new(buffer+sizeof(*p1)) People("lol"); // 留出*p1的空间,防止*p2覆盖*p1
p1->show();
p2->show();
// 这里使用 new 定位符的情况下,只能通过显式调用析构函数来释放对象中的 name 指针指向的内存
// 因为 delete 只能释放 new 常规运算符所分配的地址
//delete p2,p1; // 使用这一句的话会报错!debug assertion failed!
p2->~People();
p1->~People(); // 释放顺序尽量与创建顺序相反!
delete[] buffer;
}
cin.get();
}
结果如下所示:
要注意区分new 运算符的2种含义:
- 常规new运算符,用于动态分配内存,需与delete配合使用!
- 定位new运算符,用于将对象(或基本数据类型)存储到指定内存位置,如 int *a = new((int*)1) int(2); 即将a指向内存地址为1的地方,并在该内存处放入整型2
注意不管是哪种类型,new 都是和地址相关的操作符,因此返回一个地址,等号左边必须是一个指针才可以接收!
在上面代码中无法使用 delete 的情况下,只能通过显式析构来释放对象成员中指针name指向的堆中内存。