• 文章
  • C/C++ 中的动态分配
发布
2008年2月19日 (最后更新: 2008年2月19日)

C/C++ 中的动态分配

评分: 3.7/5 (41 票)
*****
它是什么
----------

动态分配是 C/C++ 中内存的自动分配。与将数据加载到程序的数据段的声明不同,动态分配会在程序的堆栈(分配给该程序的特定 RAM 区域)上创建新的可用空间。

它通过两个函数(C 中)和两个运算符(C++ 中)来实现
malloc 和 free,new 和 delete。

为什么使用它
--------------

动态分配可能非常有用。例如,一个动态大小的数组

假设 size 是一个变量(它不是定义为常量)。如果尝试这样做,编译器会报错
两个版本
 
int array[size];


您可以做的是动态分配此内存。例如
C 版本
1
2
int *array;
array=(int *) malloc(size*sizeof(int));

C++ 版本
1
2
int *array;
array=new int[size]l



注意
由于这些数据被推送到堆栈而不是段,因此存在内存泄漏的可能性。内存泄漏是指分配的内存未在程序返回之前释放。例如,要安全地释放刚创建的数组(并正常返回程序)
C 版本
 
free(array);

C++ 版本
 
delete [] array


另一个特别的注意:delete 后面的括号只有在你最初分配了一个数组时才需要。



动态分配对于使用链表是必要的。假设已声明自引用的结构 Node,其中 nextptr 是链接
C 版本
1
2
3
4
5
6
7
struct Node *newptr;
newptr=(struct Node *) malloc(sizeof(Node));
/*We'll insert this into this linked list just
 at the second item, assuming topptr is the name
 of the top of this list.*/
newptr->nextptr=topptr->nextptr;
topptr->nextptr=newptr;

C++ 版本
1
2
3
4
5
Node *newptr;
newptr=new Node;
//We'll insert this as the second item, using topptr.
newptr->nextptr=topptr->nextptr;
topptr->nextptr=newptr;


当然,在以上两个示例中,结构 Node 中没有使用其他成员,这违背了链表的初衷。释放节点
C 版本
1
2
3
4
5
6
7
struct Node *tempptr;
/*The node we'll free is, again, the second.*/
tempptr=topptr->nextptr;
/*We'll unbind this node first, so as not to lose all of the rest of the list with it.*/
topptr->nextptr=tempptr->nextptr;
/*It's free, get rid of it.*/
free(tempptr);

C++ 版本
1
2
3
4
5
6
7
Node *tempptr;
//We'll get the second node again.
tempptr=topptr->nextptr;
//Unbind this node.
topptr->nextptr=tempptr->nextptr;
//Get rid of it.
delete tempptr;


如何使用它
-------------

C 函数的语法是
1
2
3
#include <stdlib.h>

void *malloc(size_t size)

前几个示例中的类型转换是必要的,因为 malloc 返回 void 指针。
1
2
3
#include <stdlib.h>

void free(void *);

这不需要类型转换;任何传递的参数都会被隐式降级。

C++ 中的运算符是
 
NewAlloc=new Type;

C++ 会自动为您进行类型转换。
1
2
3
4
       //If this is an array
delete [] NewAlloc;
       //Otherwise
delete NewAlloc;


更进一步
-------------

vector 和 list 等几个类使用了此功能。实现您自己的!

理解本文需要对指针和数组(及其关系)有深入的了解。我知道,我应该把这个放在最上面。

定义一个类(我将其命名为 SafeSpot),它将在对象销毁时自动处理其中定义的内存的释放。这将消除所有那些意想不到的内存泄漏。您可能希望为该类的不同分配范围尝试不同的范围(不要让临时函数对象存在于整个程序中)。

请回复,告诉我您对这篇文章的看法!
谢谢,
Graham Northup