Memory Management
Use the same form in corresponding uses of new and delete
eryar@163.com
对应的new和delete要采用相同的形式
用new operator时会发生两件事:首先,内存通过operator new被分配;然后,为被分配的内存调用一个或多个构造函数。
用delete operator时也会发生两件事:首先,为将释放的内存调用一个或多个析构函数;然后,通过operator delete释放内存。
对于delete operator来说会有这样一个重要的问题:内存中有多少个对象需要被删除呢?删除多了,程序也就崩溃了;删除少了,就有内存未被正确释放。这个问题简单来说就是:要被删除的指针指向是单个对象,还是对象数组?这只有你来告诉delete operator。如果你在用delete operator时没有括号,delete就会认为指向的是单个对象;否则它就会认为指向的是一个数组。
Prefer new and delete to malloc and free
malloc和free(及其变体)会产生问题的原因在于它们太简单:他们不知道构造函数和析构函数。(有时越简单越好。)
假设用两种方法给一个包含10个string对象的数组分配空间,一个用malloc,另一个用new:
其结果是,stringarray1确实指向的是可以容纳10个string对象的足够空间,但内存里并没有创建这些对象。当释放这些内存时,你一定会这么做:
调用free将会释放stringarray1指向的内存,但内存里的string对象不会调用析构函数。如果string对象象一般情况那样,自己已经分配了内存,那这些内存将会全部丢失。相反,当对stringarray2使用delete时,数组里的每个string对象都会在内存释放前调用析构函数。即然new和delete可以这么有效地与构造函数和析构函数交互,选用它们是显然的。
把new/delete与malloc/free混用也是个坏想法。对一个用new获取来的指针调用free,或者对一个用malloc获取来的指针调用delete,其后果是不可预测的。
示例程序:
1:
2: #include <iostream>
3: using namespace std;
4:
5: class CTest
6: {
7: public:
8: CTest() { cout<<"Default constructor."<<endl; }
9: ~CTest() { cout<<"Default destrcutor."<<endl; }
10:
11: };
12:
13: int main(int argc, char *argv[])
14: {
15: cout<<"=== Test new/delete begin ==="<<endl;
16: CTest* pTestNewDelete = new CTest;
17: delete pTestNewDelete;
18: cout<<"=== Test new/delete end ==="<<endl;
19:
20: cout<<"~~~ Test malloc/free begin ~~~"<<endl;
21: CTest* pTestMallocFree = static_cast<CTest*> (malloc(sizeof(CTest)));
22: free(pTestMallocFree);
23: cout<<"~~~ Test malloc/free end ~~~"<<endl;
24:
25: return 0;
26: }
27:
输出:
1 === Test new/delete begin ===
2 Default constructor.
3 Default destrcutor.
4 === Test new/delete end ===
5 ~~~ Test malloc/free begin ~~~
6 ~~~ Test malloc/free end ~~~
7
来源:
1. Scott Meyers Effective C++