示信息的析构函数

delete pcl;
delete pc3;

// free buffer

// get a block of memory

其中指针pc3相对于pcl的偏移量为JustTesting对象的大小。
第二个教训是,如果使用布局new操作符来为对象分配内存,必须确保其析构函数被调用。但如何确
保呢?对于在堆中创建的对象,可以这样做:
delete pc2; // delete object pointed to by pc2
然而,对于使用布局new操作符创建的对象,不能像下面这样做:
// delete object pointed to by pc1? NO! Reason #1
// delete object pointed to by pc2? NO! Reason #2
原因在于delete可与常规new操作符配合使用,但不能与布局new操作符配合使用。例如,指针pc3
没有收到new操作符返回的地址,因此delete pc3将导致运行阶段错误。在另一方面,指针pcl指向的地
址与buffer相同,但buffer是使用new[]初始化的,因此必须使用delete[]而不是delete来释放。即使 buffer
是使用new而不是new[]初始化的,delete pcl也将释放buffer,而不是pcl。这是因为new/delete系统知
道已分配的512字节块buffer,但对布局new操作符对该内存块做了何种处理一无所知。
该程序确实释放了buffer:
delete (] buffer;
正如上述注释指出的,delete[]buffer;释放使用常规new操作符分配的整个内存块,但它没有为布局
new 操作符在该内存块中创建的对象调用析构函数。读者之所以知道这一点,是因为该程序使用了一个显
示信息的析构函数,该析构函数宣布了“Heapl”和“Heap2”的死亡,但却没有宣布“Just Testing”和“Bad
Idea”的死亡。
这种问题的解决方案是,显式地为使用布局new操作符创建的对象调用析构函数。正常情况下将自动
调用析构函数,这是需要显式调用析构函数的少数几种情形之一。显式地调用析构函数时,必须指定要销
毁的对象。由于有指向对象的指针,因此可以使用这些指针:
pc3->>JustTesting(); // destroy object pointed to by pc3
pcl->=JustTesting(); // destroy object pointed to by pc1
程序清单12.9对布局new操作符使用的内存单元进行管理,加入到合适的delete和显式析构函数调用,
从而修复了程序清单12.8中的问题。需要注意的一点是正确的删除顺序。对于使用布局new操作符创建的
对象,应以与创建顺序相反的顺序进行删除。原因在于,晚创建的对象可能依赖于早创建的对象。另外,
仪当所有对象都被销毁后,才能释放用于存储这些对象的缓冲区。

程序清单 12.9 placenew2.cpp
// placenew2.cpp -- new, placement new, no delete
#include
#include
#include
using namespace std;
const int BUF = 512;

class JustTesting

private:
string words;
int number;
public:
JustTesting(const string 6 s - "Just Testing", int n = 0)
(words = s; numher = n; cout << words << " constructed\n"; }
-JustTesting() { cout << words << " destroyed\n"; }
void Show() const { cout << words << ", " << number << endl; )

int main()

char * buffer = new char[BUF];

JustTesting *pcl, *pc2;

你可能感兴趣的:(c++,算法,开发语言)