首先我们来谈谈malloc与free
malloc和free是C函数库提供的两个函数,malloc从堆上(也叫自由存储区)分配一块合适的内存,程序返回一个指向这块内存的地址。free函数把它归还给内存池供以后使用。
注意的是这块内存并没有以任何形式进行初始化,如果进行初始化:要么自己动手进行初始化,要么使用calloc函数。
两个函数原型:
void *malloc(size_t size);
void free(void *pointer);
malloc的参数就是需要分配的内存字节数(注意malloc不能自动计算字节大小,必须直接传字节数),如果内存池的内存满足这个需求,malloc就会返回一个指向被分配的内存块起始位置的指针;如果内存池为空或者不能满足你的分配需求,malloc将返回一个NULL指针(这点很重要,每个从malloc分配的内存返回的指针用的时候都要检查是否为NULL)。
free函数的参数要么是NULL(不会产生任何效果),要么就是就是先前从malloc返回的值。只有这两种。释放一块内存的一部分是不允许的,动态分配的内存必须整块一起释放,但是有realloc的特性(缩小一块动态分配的内存),可以有效的释放他尾部的部分内存
注意观察的人会发现malloc返回的是一个 void*,那我们在内存上存储整数,浮点数和其他类型的时候该怎么办?
由于malloc返回的void*的指针,所以就表示该类型的指针可以转换为其他任何类型的指针,一般我们也经常会进行强制转换。
pi=(int *)malloc(100);//这就是讲malloc返回的指针强制转换为int型的指针。 pi=(int *)malloc(25*sizeof(int));//这是和上面的效果一样的语句,但是我们经常用这个,因为可移植性好。
下面我们谈谈new和delete
C++中的解决方案是把创建一个对象所需的所以动作都结合在一个成为new的运算符里。
new创建一个对象时,他就在队里为对象分配内存并为这块内存调用构造函数。
Mytype *fp=new MyType(1,2);
上面这个例子等价于调用了malloc(sizeof(MyType)),并使用(1,2)参数列表来为MyType调用构造函数,this指针指向返回值的地址。
默认的new还进行检查一确信在传递地址给构造函数之前内存分配是成功的,所以不用显示的确认是否成功。
delete表达式首先调用析构函数,然后在释放内存。(通常是free())
delete需要一个对象的地址。
delete fp;//删除单一对象
delete释放时,很可能出错:
例子:
string *stringArray = new string new[100]; delete stringArray;//这个程序还有99个对象没有释放
正确的写法:
delete [] stringArray;
如果你在调用new是使用了[],则你必须在调用delete是用[];如果你在调用new是没有用[],那么你在调用delete是也不应该使用[]。
区别和联系:
1,new与delete和malloc与free都可以动态的分配内存和释放内存,而且都在堆上进行分配;
2,new和delete是c++操作符;malloc和free是C/C++库函数;
3,new返回时指定类型的指针,并且可以自动计算所需的内存大小;malloc必须有我们自己计算所需的分配的内存大小,并且返回后强制转换为实际类型的指针;
4,由于malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符。对于非内部数据类的对象而言,只用maloc/free函数是不能够满足动态对象的要求。对象在创建的同时要自动执行构造函数, 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加malloc/free。而new和delete是操作符在创建对对象的时候调用构造函数,在释放对象之前调用析构函数。
new与delete成对使用,malloc和free成对使用,混合在一起并不好,例如:用malloc创建动态对象是用delete来释放,因为new和delete实现机制都是有了malloc()和free(),所以很可能在没有析构的时候就释放了内存。所以我们一定要配对的使用。
由于malloc和free对于构造函数和析构函数一无所知,并且将malloc/free与new/delete混合使用会带来很多麻烦,所以在C++中尽量使用new和delete这对组合。
2015,12.13
今天看了c的动态分配内存,顺便贴贴malloc()和calloc()的区别。
Both the malloc() and the calloc() functions are used to allocate dynamic memory. Each operates slightly different from the other.
malloc() takes a size and returns a pointer to a chunk of memory at least that big:
void *malloc( size_t size );
calloc() takes a number of elements, and the size of each, and returns a pointer to a chunk of memory at least big enough to hold them all:
void *calloc( size_t numElements, size_t sizeOfElement );
There are one major difference and one minor difference between the two functions.
The major difference is that malloc() doesn't initialize the allocated memory. The first time malloc() gives you a particular chunk of memory,
the memory might be full of zeros. If memory has been allocated, freed, and reallocated, it probably has whatever junk was left in it.
That means, unfortunately, that a program might run in simple cases (when memory is never reallocated) but break when used harder (and when memory is reused).
calloc() fills the allocated memory with all zero bits. That means that anything there you are going to use as a char or an int of any length, signed or unsigned,
is guaranteed to be zero. Anything you are going to use as a pointer is set to all zero bits.That is usually a null pointer, but it is not guaranteed.
Anything you are going to use as a float or double is set to all zero bits; that is a floating-point zero on some types of machines, but not on all.
The minor difference between the two is that calloc() returns an array of objects; malloc() returns one object. Some people use calloc() to make clear that they want an array.