本文共 2595 字,大约阅读时间需要 8 分钟。
如有错漏,还望指摘!
以前看到的资料都说,new和delete、new[]和delete[]、malloc和free,必须配套使用,不应该混用。
然而我最近遇到一些相关的问题,因此不得不探究一下,混用了会怎么样呢? 其实要想知道能不能混用,问题在于:他们有什么区别? 其实很简单:但是这里其实有一个问题:
delete[]是如何知道到底需要调用多少次析构函数的呢? 原来,new[]在分配时,如果类中显式定义了析构函数,new会在分配的时候,根据系统的位数额外分配对应的空间(32位系统分配32位空间,也就是4字节,64位系统分配64位空间,也就是8字节)。如对于32位系统,new[2]分配的空间应该如下: 在返回的指针之前,还有一个4字节的header,其中存储了分配的个数,如这里就应该是2。所以我们很容易就能得出结论:
代码:
//构造函数和析构函数都没有作用。可以随意混用。class test1{ public: test1(){ }}int main(void){ /* 这里用任意方式分配的内存都可以用任意方式释放 */ //test1 *ptr = new test1; test1 *ptr = new test1[3]; //test1 *ptr = (test1*)malloc(sizeof(test1)); //delete ptr; //delete[] ptr; free(ptr);}
//构造函数有作用。//没有显示定义析构函数,因此delete、delete[]、free可以混用class test2{ public: test2(){ init(); } inline void init(){ cout << "constructor" << endl; }}int main(void){ //test2 *ptr = new test2; //test2 *ptr = new test2[3]; /* 这里如果想用malloc,必须显示调用构造函数的逻辑。 注:由于构造函数无法被显式调用,因此必须另写一个其实现逻辑,也就是这里的init()函数。 */ test2 *ptr = (test2*)malloc(sizeof(test2)); ptr->init(); //delete ptr; delete[] ptr; //free(ptr);}
//构造函数没有有作用。new、new[]、malloc可以混用//显示定义析构函数class test3{ public: test3(){ } ~test3(){ cout << "destructor" << endl; }}int main(void){ //test3 *ptr = new test3; test3 *ptr = (test3*)malloc(sizeof(test3)); //delete ptr; /* 必须显示调用析构函数 */ ptr->~test3(); free(ptr); /* 只要定义了析构函数,即使析构函数内是空的,delete[]和new[]也必须配套使用,否则会一直调用析构函数 */ //test3 *ptr = new test3[3]; //delete[] ptr;}
//对于32位系统,new[]和delete[]的非配套使用。//显示定义析构函数class test3{ public: test3(){ } ~test3(){ cout << "destructor" << endl; }}int main(void){ int n = 3; /* new[]和free混用 */ test3 *ptr1 = new test3[n]; //模拟delete[] for(int i = 0; i < n; i++){ (ptr1 + i)->~test3(); } ptr = (test3*)( ((char*)ptr) - 4 ); free(ptr); /* malloc和delete[] */ //模拟new[] test3* ptr2 = (test3*)malloc(4 + n * sizeof(test3)); //如果是64位系统,这里4换成8 int32_t* temp = (int32_t*)ptr2; //如果是64位系统,这里是int64_t *temp = n; temp++; ptr2 = (test3*)temp; for(int i = 0; i < n; i++){ (ptr2 + i)->init(); } delete[] ptr2;}
转载地址:http://pxxzi.baihongyu.com/