1、C malloc 和 free vs C++ new 和delete:
C 语言的malloc() 和free() 并不会调用析构函数和构造函数。C++的 new 和 delete 操作符 是 "类意识" ,并且当调用new的时候会调用类的构造函数和当delete 调用的时候会调用析构函数。
下面一个例子
// memory.cpp : 定义控制台应用程序的入口点。 //2011/10/13 by wallwind #include "stdafx.h" #include <iostream> using namespace std; class SS { public: SS(); ~SS(); private: int ff; int gg; }; SS::SS() { ff=5; cout << "Constructor called" << endl; } SS::~SS() { cout << "Destructor called" << endl; } int _tmain(int argc, _TCHAR* argv[]) { SS *ss; ss = new SS; // new operator calls constructor. delete ss; // delete operator calls destructor. return 0; }运行结果:
如图一
注意:混合用malloc 和delete或者混合用new 和free 是不正确的。C++的new和delete是C++用构造器分配内存,用析构函数清除使用过的内存。
new/delete 优点:
-
new/delete调用 constructor/destructor.Malloc/free 不会.
-
new 不需要类型强制转换。.Malloc 要对放回的指针强制类型转换.
-
new/delete操作符可以被重载, malloc/free 不会
-
new 并不会强制要求你计算所需要的内存 ( 不像malloc)
2、C 的动态内存分配:
看如下例子MallocTest.cpp
// memory.cpp : 定义控制台应用程序的入口点。 //2011/10/13 by wallwind #include "stdafx.h" #include <iostream> using namespace std; typedef struct { int ii; double dd; } SSS; int _tmain(int argc, _TCHAR* argv[]) { int kk, jj; char *str1="This is a text string"; char *str2 = (char *)malloc(strlen(str1)); SSS *s1 =(SSS *)calloc(4, sizeof(SSS)); if(s1 == NULL) printf("Error ENOMEM: Insufficient memory available\n"); strcpy(str2,str1); //Make a copy of the string for(kk=0; kk < 5; kk++) { s1[kk].ii=kk; } for(jj=0; jj < 5; jj++) { printf("Value strored: %d\n",s1[jj].ii); } free(s1); free(str1); free(str2); }结果:
图二
注意:
3、C++ 动态内存分配:
使用 "new" 和 "delete"
如下示例:文件: AllocNewTest.cpp
// memory.cpp : 定义控制台应用程序的入口点。 //2011/10/13 by wallwind #include "stdafx.h" #include <iostream> using namespace std; class CCC { public: CCC(){cout<<"CCC()"<<endl;}; ~CCC(){cout<<"~CCC()"<<endl;}; CCC(int); CCC(int, double); int ii; double dd; }; CCC::CCC(int _ii) : ii(_ii) { }; CCC::CCC(int _ii, double _dd) : ii(_ii), dd(_dd) { }; int _tmain(int argc, _TCHAR* argv[]) { CCC *cc1 = new CCC(4, 5.5); // Pointer. Contructor called. CCC *cc2 = new CCC[5]; // Pointer to an array of objects. CCC &cc3 = *new CCC; // Reference CCC **c4 = new CCC * [5]; // Array of pointers to pointers cc1->ii = 5; cc2[3].ii = 6; cc3.ii = 7; c4[0] = new CCC(8); c4[1] = new CCC(9); cout << cc1->ii << endl; cout << cc2[3].ii << endl; cout << cc3.ii << endl; cout << c4[0]->ii << endl; cout << c4[1]->ii << endl; delete cc1; delete [] cc2; delete & cc3; delete [] c4[0]; // First delete pointer content delete [] c4[1]; delete [] c4; // then delete array of pointers return 0; }注意:
-
new CCC(3) 为integer 成员的单个对象分配的内存并且设置integer 成员成3.
-
new CCC[3] 创建三个对象,并没有初始化变量
结果如图:
图四
4、C 函数返回一个指针vs C++函数返回的是一个副本:
C 函数返回一个指针
// memory.cpp : 定义控制台应用程序的入口点。 //2011/10/13 by wallwind #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <iostream> using namespace std; char *fnConvert(int _ii) { char *str =(char*)malloc(10); /* Return 10 character string */ if(str == NULL) fprintf(stderr,"Error: Memory allocation failed.\n"); sprintf(str, "%d", _ii); return str; } int _tmain(int argc, _TCHAR* argv[]) { char *s1=fnConvert( 34567 ); printf("%s\n", s1); free(s1); return 0; }运行结果:
图五
C++ 函数返回的是一个副本:
// memory.cpp : 定义控制台应用程序的入口点。 //2011/10/13 by wallwind #include "stdafx.h" #include <iostream> #include <sstream> #include <string> using namespace std; string fnConvert(int _ii) { ostringstream ost; ost << _ii; return ost.str(); } int _tmain(int argc, _TCHAR* argv[]) { cout << fnConvert( 34567 ) << endl; return 0; }运行结果
图六
注意:c++的STL string类的赋值构造函数是被用来返回一个值的副本,也就是当我们离开了函数的时候,变量 "ost",不在作用域了,但是所赋复制的内容是有效的。不要返回"return ost.str().c_str()" 作为他的指针,他是不在作用域的内一旦程序离开了函数,并且数据会丢失。
5、C++ 动态内存分配的异常处理:
// memory.cpp : 定义控制台应用程序的入口点。 //2011/10/13 by wallwind #include "stdafx.h" #include <iostream> #include <sstream> #include <string> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { int ii; double *ptr[5000000]; try { for( ii=0; ii < 5000000; ii++) { ptr[ii] = new double[5000000]; } } catch ( bad_alloc &memmoryAllocationException ) { cout << "Error on loop number: " << ii << endl; cout << "Memory allocation exception occurred: " << memmoryAllocationException.what() << endl; } catch(...) { cout << "Unrecognized exception" << endl; } return 0; }运行:
-
观察系统约束: ulimit -a
-
设置系统约束: ulimit -m 100
-
以很小的优先权运行: nice -n 19 AllocNewTest
6、C++ Virtual Destructors
// memory.cpp : 定义控制台应用程序的入口点。 //2011/10/13 by wallwind #include "stdafx.h" #include <iostream> #include <sstream> #include <string> using namespace std; class Base { public: Base(){}; virtual ~Base(){ cout << "Base class destructor called" << endl; } }; class Derived : public Base { public: Derived(){}; ~Derived(){ cout << "Derived class destructor called" << endl; } }; int _tmain(int argc, _TCHAR* argv[]) { Base *ptr = new Derived(); delete ptr; return 0; }
运行结果:
图七
注意:
- 如果删除操作符被应用在基类中,并且其析构函数并不是虚函数,这将会引起内存泄露,因为只有基类的内存被释放掉。
- 基类的析构函数不是纯虚函数,将不能被作为基类而实现。
- 类的析构函数可以不是virtual