C语言提供了动态内存分配(dynamic memory allocation)函数malloc和free及malloc的变体alloca.calloc,realloc等。其中alloca是向栈申请内存,因此无需释放。malloc从堆中申请内存,并且没有初始化内存的内容,里面存的是垃圾数,因此我们一般用memset来初始化这部分的内存空间。calloc则将初始化这部分的内存,设置为0,而realloc则对malloc申请的内存进行大小的调整。
malloc、calloc、free都是库函数,使用时需包含stdlib头文件,跟os无关,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务加给malloc/free。
maclloc原型:extern void * malloc(unsigned int num_bytes);
它申请长度num_bytes字节的内存块。如果分配成功则返回指向被分配内存的指针,返回类型是void 类型,void 表示未确定类型的指针,c/c++规定,void * 类型可以强制转换为任何其他类型的指针。分配失败返回空指针。
#include <cstdlib> // malloc & free
#include <cstring> // memset
#include <iostream>
using namespace std;
class obj
{
int i, j, k;
enum{sz = 100};
char buf[bz];
public:
void initialize()
{
cout << "initializing Obj" << endl;
i = j = k = 0;
memset (buf, 0, sz);
}
void destroy() const
{
cout << "destroying Obj" << endl;
}
};
int main()
{
Obj * obj = (Obj* )malloc(sizeof(Obj));
obj->initialize();
obj->destroy();
free(obj);
}
这行代码中Obj * obj = (Obj* )malloc(sizeof(Obj));用户必须决定对象的长度(这也是程序出错的原因之一)。由于malloc只是分配了一块内存而不是生成了一个对象,所以它返回了void*类型指针。而c++不允许将一个void*类型指针赋予任何其他指针,所以必须做类型转换。
C语言的动态内存分配机制太复杂,容易令人混淆。C++的解决方案是把创建一个对象所需的所有动作都结合在一个称为new的运算符里。当用new创建一个对象时,它就在堆里为对象分配内存并为这块内存调用构造函数。因此,如果写出下面的表达式:
MyType *fp = new MyType(1,2);
在运行时等价于调用malloc(sizeof(MyType)),并使用(1, 2)作为参数表来为MyType调用构造函数,this指针指向返回值的地址。在指针被赋给fp之前,它是不定的、初始化的对象–在这之前我们甚至不能触及它。它自动地被赋予正确的MyType类型。
默认的new还进行检查以确信在传递地址给构造函数之前内存是分配成功的,所以不必显示的确定调用是否成功。
现在在堆里创建对象的过程变得简单了–只是一个简单的表达式,它带有内置的长度计算、类型转换和安全检查。
本文深入解析C语言中动态内存分配的关键函数,包括malloc、calloc、free以及对象创建过程。通过实例代码,详细阐述了如何在C语言中高效管理内存,并对比了不同内存分配函数的使用场景与特性。此外,文章还介绍了C++的解决方案——new运算符,简化了对象创建过程,避免了内存分配和初始化的复杂性。
784

被折叠的 条评论
为什么被折叠?



