首页 > 编程知识 正文

动态内存分配生成动态数组,c语言内存分配与释放

时间:2023-05-04 06:49:55 阅读:9502 作者:428

背景:

对计算机编程来说,变量和对象在内存中的分配是编译器在编译程序时安排的,给我们带来了很大的不便,比如必须增大和减小数组。 (增大或减小意味着数组容量为100,实际使用10会增加内存浪费。 ) )因此,为了解决这个问题。 我们为了解决这个问题引入了动态内存分配。

一、动态内存的使用方法

因为new返回指针类型,所以必须用相同类型的指针接受。 在某些特殊情况下,继承时可以用父指针指向子类对象。

new和delete运算符是用于动态分配和撤消内存的运算符。

1 .要打开单变量地址空间并使用new运算符,您必须知道数据类型。 new运算符请求系统堆空间的足够存储空间,如果请求成功,则返回该内存块的起始地址;如果请求失败,则返回零值。

new运算符返回指向分配的类型变量(对象)的**指针**。 由于创建的变量或对象是由**指针**间接操作的,因此动态创建的对象本身没有标识符名称。

常用使用格式:

格式1 :指针变量名称=new类型标识符;

格式2 :指针变量名=new类型标识符(初始值);

格式3 :指针变量名=new型识别符[存储单元数]

说明:格式1的写法只是申请空间,不对其赋值进行初始化。

格式2内存分配成功后,同时将初始值存储在其存储单元中,如果只写括号也不写具体值,则默认用0初始化该对象;

在格式3中,可以同时分配多个存储单元,这相当于形成动态数组。

例如:

1 )新建int; 打开保存//整数的存储区域,返回指向该存储区域的地址。 int *a=new int是为整数指针a分配int类型的地址

2 ) int *a=new int(5) 5作用相同,但同时将整数空间代入5

2 .打开一维数组空间对数组动态分配的形式如下:

指针变量名称=new类型名称[下标表达式]

指向delete [ ]数组的指针变量名称;

表达式中的方括号非常重要,必须成对使用两者。 如果delete语句不包含方括号,编译器将该指针识别为指向数组中第一个元素的指针,从而导致回收不完整。 添加方括号将转换为指向数组的指针,并回收整个数组。

不需要在delete []的方括号中键入数组元素的数量。 系统知道。 即使写了也无视编译器。

请注意,“下标表达式”不必是常量表达式。 也就是说,该值在编译时不需要确定,而是可以在运行时确定。

一维:int t; cin t; int* a=new int[t]; //这个一维数组是运行时确定的空间

3 .开拓多维数组的写法和用法。 左半部分:类型名称(*指针名称) [阵列第二次元长度] ) [阵列第三次元长度] ……。

右半部:new类型名称[数组第一维长度][数组第二维长度][数组第三维长度] ……………。

有两个注意事项:

1 .不要忘记左半部分的括号

2 .左大括号中的维度比右边少第一个维度。

int(*p ) [3]=newint ) [2][3]; //二维int(P1 ) [2][3]=newint )1) [2][3]; //三维

4、删除delete用法1 .删除单变量地址空间

int *a=new int;

电传a; //释放各个int的空间

2 .删除数组空间,

int *a=new int[5];

delete []a; 释放//int数组空间。 注意,即使是多次元数组,也只需在最后的delete后面写[]即可。

2 )动态内存分配和我们自定义类相遇时的注意事项。 既然是自定义类,构造函数问题就不可避免。

如果自定义类包含用户定义的默认构造函数,则new T和new T ) )是否加括号是相同的。

但是,如果用户没有定义默认的复制构造函数,此时就会有差异。 使用new T时,将调用系统的隐式构造函数。 另一方面,new T ) )将0赋值给所有基本数据类型和指针类型,而不仅仅是系统的隐式构造函数。 这个过程是递归的,什么是递归? 当一个类包含另一个自定义类型时,所有到该自定义类都用0初始化。

//先给你上课,class point {public: int m_a; int m_b; point (); point () { this-m_a=m_a; this-m_b=m_b; }

 void print(int m_a, int m_b) {        cout << m_a << "  " << m_b << endl;    }};

1.创建单独类的对象 

//调用无参构造函数

point *p=new point;

//调用有参构造函数

point *p=new point(1,3)

 2.创建自定义类数组

point* p = new point[10];

 

point* p = new point[10]();

用法:

point* p = new point[10];
p[1].m_a = 1;
p[1].m_b = 2;
p[1].print();
 delete []p;

三、使用注意事项

1. new 和delete都是内建的操作符,语言本身所固定了,无法重新定制,想要定制new和delete的行为,徒劳无功的行为。

2. 动态分配失败,则返回一个空指针(NULL),表示发生了异常,堆资源不足,分配失败。所以使用时尽量先判断一下(if(指针变量名!=NULL)

3. 指针删除与堆空间释放。删除一个指针p(delete p;)实际意思是删除了p所指的目标(变量或对象等),释放了它所占的堆空间,而不是删除p本身(指针p本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放),释放堆空间后,p成了空指针。

4. 内存泄漏(memory leak)和重复释放。new与delete 是配对使用的, delete只能释放堆空间。如果new返回的指针值丢失,则所分配的堆空间无法回收,称内存泄漏,同一空间重复释放也是危险的,因为该空间可能已另分配,所以必须妥善保存new返回的指针,以保证不发生内存泄漏,也必须保证不会**重复释放**堆内存空间。(千万小心,别把系统整瘫痪)。

5. 动态分配的变量或对象的生命期。我们也称堆空间为自由空间(free store),但必须记住释放该对象所占堆空间,并只能释放一次,在函数内建立,而在函数外释放,往往会出错。

6. 要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问。

    用new和delete可以动态开辟和撤销地址空间。在编程序时,若用完一个变量(一般是暂时存储的数据),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。