《More Effective C++》8:了解各种不同意义的new和delete
new operator 和 operator new
当你写出这样的代码时,实际上你调用的是所谓的new operator:
string* pS = new string("Hello, New Operator.");
呵呵,别纠结,我们来理一理它们的“情感纠纷”。
其实,当我们在做上面的所谓new operator操作时,做了两件事情,
其一,开辟用来存string对象的空间;
其二,调用该对象的构造函数,将该对象初始化。
第一步的操作,实际上是编译器在调用一个专管分配内存的操作符,这就是所谓的operator new操作符,
它和malloc函数一样,唯一的任务就是内存分配,因此,上面的那段代码的具体实现是这样的:
void* memory = operator new(sizeof(string));//开辟string对象的空间
调用string::string("Hello, New Operator.")将memory初始化
string * pS = static_cast<string*>(memory); //让pS指向新创建的对象
placement new
在已经分配好空间的原始的,未初始化的内存中,如何构造对象呢?
显然直接调用构造函数就有点奇葩了,毕竟构造函数是在创建新对象时候初始化对象的,
而现在针对的是在已建空间上构建对象。
有一个特殊的operator new,名为placement new可以实现该内容。
看下面的例子:
void* memory = operator new(sizeof(string));//开辟string对象的空间
cout << "memory指向的空间:" << memory << endl;
string* p = new (memory) string("hello, new operator.");
cout << "p指向的空间: " << p << endl;
cout <<"p指向的内容:" << *p << endl;
效果: string* p = new (memory) string("hello, new operator."); 从结果来看,这句话就是在把分配到memory的内容初始化为string。
这就是所谓的placement new.
删除(Deletion)和内存释放(Deallocation)
为了避免资源泄露(Resource Leaks)。每一个动态分配行为,都必须有一个与之对应但相反的释放动作。
因此,函数operator delete 之于内建的 delete operator,相当于 operator new 之于 new operator。
当做下面的操作时,
- delete pS;
- pS->~string();
- operator delete(pS);
数组
当然,在之前我们一直谈到的是分配单一对象的空间,要是我们要用 new operator产生一个数组空间,就会有所不同。
在分配内存阶段,‘不能再调用 operator new来操作,而是调用一个名为 operator new[ ]的函数负责分配内存。
同样道理,当delete operator 被用于数组,它就会针对每一个对象调用其析构函数,
然后调用其operator delete[ ]函数释放内存。