c/c++ 内存管理

一、关于c

 我们知道在c语言中栈上申请空间方式有三种:

   (1)void* malloc(字节):申请一块内存(无初始化)

   (2)void* calloc(单个元素字节,个数):给出空间并初始化为0

   (3)void* realloc(地址p,字节数):改变p的指针指向大小。

我们详谈realloc:

     1)若p==NULL,他就和malloc是一样的作用。

    2)若非空:-->newsize--->(1)newsize<=oldsize:直接返回p (2)newsize>oldsize--->1)大了一点点:返回p  2)大了很多(没找到返回NULL)    ->(1)重新找一个新的newsize的字节内存块 (2)将旧空间的元素拷到新空间  (3)释放旧空间  (4)返回新空间p

释放空间我们采用free(指针):

常见的内存泄漏:

  (1)内存忘记释放

  (2)程序逻辑不清,以为释放了,实则没释放

  (3)将堆破坏

  (4)释放时传入的空间和释放时穿入的空间地方不相同。

我们如何进行检测:

   (1)系统有一个自带工具

   (2)自己写一个(难度较大)

   (3)VLD工具

我们可以对这种问题进行预防

   (1)良好的代码规范

   (2)智能指针

二、c++

可以继续使用c里面,同时自己又提出了:new/delete    new[]/delete[]

  (1)   对于内置类型,若没有匹配使用,不会造车内存泄漏。

(2)对于自定义类型,且析构函数显示给出,若没有搭配使用:(1)内存泄漏 (2)程序崩溃

                                      若析构函数未给出,没有搭配使用,可能大致内存泄漏,不会崩溃。

详谈new:

做了两件事:

(1)调用void* operator new(szie_t size)函数申请空间-->这个函数的内部其实也是用malloc来完成空间申请的:

                  1)成功(返回地址)   

                 2)失败(空间不足)---> 内部完成对空间不足做出的应对措施(提供了一个函数,用户自己来提供,检测是否存在已经申请的但不使用的空,没有就出错,抛一个异常)

(2)调用构造函数初始化对象。

详谈delete

做了两件事:

(1)调用析构函数:清理对象中的资源

(2)调用void* operator delete(size_t size)释放空间,其也是对free的封装。

再来说说malloc内部干的事

   比如:int* p=(int *)malloc(sizeof(int)*10) 我们此时是申请了40个字节,但其实它内部需要管理,每个都会多申请36个字节。

详谈new T[N]:

做了两件事:

  (1)调用void* operator new[] ,他又会调用operator new-->malloc

    (2)   调用N次析构函数。 其实他在申请空间的时候会在多申请4个字节的空间,来记录对象的个数。(若没有析构函数,就不用记录,这里记录对象的个数,其实是为了在析构的时候知道应该析构多少次)。

详谈:delete[] pt

做了两件事:

 (1)清理对象中的资源-->去空间前4个字节中取字节个数N,调用析构(N次)  (倒着销毁,最后一个对象创建的最晚,生命周期短)。

(2)调用operator delete[] (从空间的起始位置释放)->operator delete-->free

  总结:

1)无析构 

          malloc-->delete/delete[]->底层都是用free实现的

          new-->delete/delete[]-->底层都是用free实现的

          new[]-->delete/delete[]->底层都是用free实现的

2) 有析构

         new->free:对象资源没有清理

                  ->delete[]:崩溃(多释放4字节)

         new[]->free:对象资源无清理&不会从起始位置进行释放,崩溃

                  ->delete:只会销毁一个对象(N-1)个对象没有清理&不会从起始位置释放

因此我们在使用  new/delete    new[]/delete[]  一定要搭配使用

对于void* operator new(size_t size)--->用户可以提供

(1)类成员函数  (2)普通成员函数  (3)库函数

定位new表达式:

     在已存在的空间上执行构造函数。

假如我们要申请1000块空间,每次都会调用malloc,前面说过,每调malloc一次内部会多出36个字节,那此时就多出了36000个字节,这是极大的浪费。

因此我们一次性malloc一大块,每次拿的时候直接从malloc出来的那块空间里面拿就可以了。但是有一个问题,malloc出来的不会进行构造,因为我们需要采用new(地址) 类型,对其进行类的构造。此时它内部调用  operator new(size_t ,void* where ){return where;}   不需要指定大小,只需给位置就行。

两个问题:

(1)c库malloc和free等来动态管理内存,为什么c++还要定义new和delete运算符来动态管理内存呢?

     答:因为c库里面的无法将对象正确构造和释放

(2)malloc/free和new/delete的区别:

   1)malloc free是c库的函数,new delete是c++的操作符

   2)malloc free只是动态分配和释放空间,new delete除了分配空间还会调用构造和析构函数

   3)malloc  需要手动计算类型大小且返回值为void*,需要强转。new可以自己计算大小,返回相应类型的指针

   4)malloc需要判空  new有自己的应对措施-->抛异常,不需要对结果进行判空,会捕获异常

   5)malloc不可初始化   new可以

   6)malloc在堆上   new不一定在堆上(可以自己写)

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在C/C++编程语言中,内存是一个非常重要的概念。内存是计算机用于存储和访问数据的地方,它可以被看作是一个巨大的存储器数组,每个元素都有一个独特的地址。 在C/C++中,我们可以使用指针来访问和操作内存。指针是一个特殊类型的变量,它存储了一个内存地址。通过指针,我们可以间接访问和修改内存中的数据。 当我们在程序中声明一个变量时,系统会为该变量分配一块内存空间,并将其地址存储在变量名中。我们可以通过使用变量名来访问和修改该内存空间中的值。 另外,我们可以使用动态内存分配函数来在运行时动态地分配内存。这在需要在程序中创建变量长度的数组或者临时存储空间时非常有用。动态内存分配函数包括malloc、calloc和realloc。在使用这些函数分配内存后,我们需要记得通过使用free函数来释放这些内存空间。 值得注意的是,C/C++中的内存管理是程序员的责任。这意味着我们在使用指针和动态内存分配函数时需要小心,以避免内存泄漏和悬挂指针等问题。我们需要确保我们在使用完内存后及时释放它,以避免浪费内存资源。 总结来说,C/C++中的内存是一个重要的概念,我们可以使用指针来访问和操作内存。通过动态内存分配函数,我们可以在程序运行时动态地分配内存。然而,我们也需要负责管理内存,以避免出现内存泄漏和悬挂指针等问题。 ### 回答2: C/C++中的内存填空题是指填写一段代码,完成特定的内存操作。以下是一个例子: ```c #include <stdio.h> int main() { int array[5]; // 声明一个包含5个整数的数组 int *p = array; // 声明一个指向数组首元素的指针 // 使用循环将数组中的元素赋值为0到4 for (int i = 0; i < 5; i++) { *(p + i) = i; } // 打印数组中的元素 for (int i = 0; i < 5; i++) { printf("%d ", array[i]); } return 0; } ``` 在这个例子中,我们声明了一个包含5个整数的数组`array`,然后使用指针`p`指向数组的首元素。接下来,通过循环遍历数组,利用指针`p`对数组元素进行赋值操作,赋值的值为数组下标。最后,再通过循环遍历数组,利用数组`array`打印出各个元素的值。这段代码展示了C/C++中的指针和数组的使用,以及对内存空间的操作。 ### 回答3: C/C++ 内存填空题一般涉及指针和内存管理的知识。下面给出一个例子以300字来回答: 以下是一道关于C/C++ 内存填空题的解答。 ```c #include <stdio.h> #include <stdlib.h> int main() { int* ptr = (int*)malloc(sizeof(int)); int* arr = (int*)calloc(5, sizeof(int)); *ptr = 10; for (int i = 0; i < 5; i++) { arr[i] = i; } printf("Ptr: %d\n", *ptr); printf("Arr: "); for (int i = 0; i < 5; i++) { printf("%d ", arr[i]); } printf("\n"); free(ptr); free(arr); return 0; } ``` 上述代码中包含了两个关于内存的填空处,首先是通过`malloc(sizeof(int))`来分配存储 int 类型数据的内存空间,并将其地址赋值给`ptr`指针;另一个是通过`calloc(5, sizeof(int))`来分配存储 5 个 int 类型数据的连续内存空间,并将其地址赋值给`arr`指针。 接着通过`*ptr = 10`给指针 `ptr` 所指向的内存位置赋值为 10。并用一个 for 循环给数组 `arr` 赋值为 0 到 4。 最后通过`printf`打印结果。Ptr 输出为 10, Arr 输出为 0 1 2 3 4,表示内存填空处正确。 最后需要调用`free`函数手动释放内存,以避免内存泄漏。 在实际编程中,动态内存分配是一个常见的操作,合理地申请内存并及时释放内存对于提高程序的性能和效率十分重要。因此对于这类题目要熟悉`malloc`、`calloc`、`realloc`、`free`等函数的使用规则和注意事项,以及指针的正确使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值