C/C++分配内存的那些事

首先需要知道,编译器给变量分配的内存分为三部分:静态存储区域、栈、堆。
静态存储区:主要保存全局变量和静态变量。
栈:调用函数相关的变量、地址等,底层对栈提供支持,栈的大小远小于堆的大小,向负方向生长,限定大小。
堆:存储动态生成的变量,操作由C/C++函数库提供,效率低于栈,向正方向生长,无限大小(32位可达4G)。

1.使用new与delete

ClassName *object=new ClassName(param);//单个对象
delete object;
object=null;
int *a = new int[5];//数组
delete [] a; //释放int数组空间

使用new,这个时候系统会调用构造函数,此时C++是在堆上开辟了一块空间来创建对象的,C++用new创建对象时返回的是一个对象指针(要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问),对象指针object此时指向一个ClassName的对象,C++分配给object的仅仅是存放指针值的空间。需要注意的是,使用完这个对象后,需要手动delete删除,否则在整个程序生命周期内这个对象都将会占用内存,在需要反复新建对象的工程中,长此以往将会造成内存泄漏。delete对象时会调用其析构函数,delete结束后指针需要指向null,否则可能误用此指针。
注意:该方法创建的对象调用类方法时,必须用“->”,而不能用“.”。

2.使用构造函数(显式调用和隐式调用)

class Rec
{
   public:
   Rec(int width,int height);
   ~Rec();
   int getArea();

   private:
   int Rwidth;
   int Rheight;
};
main()
{
   Rec myRec(5,5);//隐式调用
   Rec MyRec=Rec(5,5);//显式调用
}

用两种方法创建了一个myRec对象,实际上这两种方式是一样的,一种是显示调用,一种是隐式调用,此时如果打印出sizeof(myRec),会得到 8 这个结果。因为myRec中有2个int类型的数据成员,一个int成员占4个字节,所以myRec对象占8个字节。
这种方法创建的对象,内存分配是分配到栈中的,由C++缺省创建和撤销,自动调用构造函数和析构函数
注意:该方法创建的对象调用类方法时,必须用“.”,而不能用“->”如myRec.getArea()。

3.使用malloc()与free()
先来看下面的例子:

	char *p;//1
	p = (char *)malloc(10*sizeof(char));//2
	if(p!=NULL) return;
	memset(p,0,10*sizeof(char));//3
	stpcpy(p,"come on");//4
	p =(char *)realloc(p,20*sizeof(char));//5
	if(p!=NULL) return;
	strcat(p,",baby!");//6
	free(p);//7

(1)定义一个char*型指针变量p
(2)为p分配10个字节的内存空间,若申请失败则退出
(3)用0填充这个内存空间
(4)复制"come on" 字符串到p指向的内存空间
(5)将p指针指向的内存空间再扩大20个字节,若申请失败则退出
(6)将",baby!"字符复制在p指向空间字符串的后面
(7)释放p指向的空间

以上就是使用方法示例,接下来解析下相关函数:
void malloc(size_t size)*
其中参数size_t size表示动态内存分配空间的大小,以字节为单位,C++是在堆上开辟了一块空间来创建对象的。
size_t 是typedef重定义的类型,重定义这样数据类型的作用就是让使用者一目了然,指示使用者这个参数表示一个长度,在size后加上t,表示是整型相关数据类型的,以后看到xxx_t的类型,通常都是整型相关数据类型重定义。
malloc()函数的返回值是一个指针,或者说是分配后内存空间的首地址, 如果malloc()函数申请空间成功则返回一段内存空间的首地址,失败则返回NULL,失败的原因可能是内存不足,为了防止后续的操作出错,此处申请完内存后需要判断是否申请成功。malloc返回值的类型是void* ,所以在调用malloc时要显式地进行类型转换,将void * 转换成所需要的指针类型。

void memset(void s,int c,size_t n)
此函数将已开辟内存空间 s 的首 n 个字节的值设为值 c。一般用在对定义的字符串进行初始化为‘ ’或‘/0’,此处为了防止分配的内存存在无关内容,首先对其进行清空操作。

void realloc(void mem_address, unsigned int newsize)
功能为改变mem_address所指内存区域的大小为newsize长度。如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。此处将原申请空间继续扩大了。

void free(void ptr)*
功能为释放掉指定的内存空间,其中void *ptr是内存空间的首地址,与malloc成对使用。

最后再列一些new与malloc的区别:
1.首先当然是编译环境的区别,在C++中,两者都可以使用,而在C中是不支持new的;
2.失败时的区别,当new失败时会抛出bac_alloc异常,而malloc失败时返回的是空指针;
3.返回值的区别,new返回的指针是与对象匹配的并不需要转换,而malloc返回的是void类型指针,需要强转;
4.new和delete会自动调用构造函数和析构函数,但是malloc和free不会;
5.malloc可利用realloc重新分配内存,new不可以;
6.new的使用比malloc简单,内部已经实现了大小的计算、类型转换等工作,而malloc使用时需要计算大小及进行类型转换;
7.malloc是标准库函数,new是C++的运算符。所有new可以被重载,但malloc不可以,malloc需要库函数的支持,new不需要;
8.malloc可利用realloc重新分配内存,new不可以;
9.new有明确的方式处理数组的分配,即new[],释放也有delete[],malloc没有。

猜你喜欢

转载自blog.csdn.net/li3781695/article/details/85245230