C/C++之动态内存分配比较

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); }

结果:

图二

注意:

  • malloc: 用于申请一段新的地址
  • calloc: 用于申请N段新的地址
  • realloc: realloc是给一个已经分配了地址的指针重新分配空间
  • free: 通过指针释放内存

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值