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