C++内存管理(上)

简介: C++内存管理

一、C/C++内存分布


1669269764774.jpg

C语言阶段我们学习过C程序内存区域是如何划分的,C++也是这样划分程序的,只不过在使用方式上和C有所不同,我们先复习C,先看几道题目:

1669269780369.jpg

解析图:


1669269792833.jpg


上面的很多相信大家都可以轻松解决,这里只说几道容易出错的题目。


1、*char2存储在什么地方?


很多老铁可能会这样觉得,char2是常量字符串"abcd"的地址,存储在栈上,然后*char2拿到字符串的首字符'a',所以应该存储在代码段(常量区),其实不然。这里我想问老铁一个问题,如果*char2拿到存储在常量区的'a',那么我如果对char2的内容做修改,是否也要修改常量区的内容呢?显然是不可以的,常量区内容不能被修改。所以*char2应该在栈上!!我们只是把常量字符串"abcd"拷贝到了char2上,*char2还在栈上可以被修改。


2、与之相对应的就是*pchar3,pchar3是一个地址,虽然用const修饰,但他就是一个地址,没有实际内容,指向存储在代码段的常量字符串。因为他用const修饰,限制修改,没必要再拷贝。


【说明】:


1、栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。


2、内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通信。


3、堆用于程序运行时动态内存分配,堆是向上增长的。


4、数据段--存储全局数据和静态数据。


5、代码段--可执行的代码/只读常量。


二、C++内存管理方式


C++兼容C语言,C语言使用malloc、calloc、realloc管理内存,C++中可以继续使用这些内存管理方式,但是有些地方用它就不太方便,于是C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。


Ⅰ new和delete操作内置类型


C++提出用new来开辟空间,用delete来释放空间。那么我们怎么使用new和delete呢?


①new和delete的基本使用

new默认不会初始化。

1669269828326.jpg

new给初始化的方式是在内置类型后面加(),()里面是要初始化的值。

1669269841361.jpg

new想要开辟多个空间,需要加[ ],同样在delete时也需要加[ ]。


new在初始化一个空间时用(),初始化多个空间时,类似于数组,用{ },里面放初始化值,没有给初始化的后续默认是给0,如果压根没有给初始化值,那么开辟的多个空间里面默认随机值。

1669269853932.jpg


Ⅱ new和delete操作自定义类型


我们光看new和delete对内置类型,与C语言那一套难分高下,可能有优势的地方在于可以自行给初始值,而calloc最多都设为0。new和delete主要是针对自定义类型的。


1669269882652.jpg


我们看到new/delete 和malloc/free最大区别是 new/delete对于自定义类型除了开空间,还会调用构造和析构函数,这一点会给我们带来很大方便。


举个例子:之前在C语言数据结构阶段构造链表时,我们每开辟一个新节点,就要调用函数对它初始化,这里在C++我们开辟节点,就可以自动调用构造初始化,很方便。

struct ListNode
{
  ListNode(int val)
  :_next(nullptr)
  , _val(val)
  {
  }
  ListNode* _next;
  int _val;
};
int main()
{
  ListNode* n1 = new ListNode(1);
  ListNode* n2 = new ListNode(2);
  ListNode* n3 = new ListNode(3);
  ListNode* n4 = new ListNode(4);
  n1->_next = n2;
  //...
  //不用写buynode
  return 0;
}


Ⅲ new和delete要匹配使用


new和delete配套使用,用于开辟一块和销毁一块空间。new[ ]和delete[ ]配套使用,用于开辟多块和销毁多块空间。


new[ ]和delete

1669269910834.jpg

这里就会报错,析构失败。


但是,这里有个奇怪的现象,我把析构函数屏蔽掉就不会报错!

1669269921558.jpg

这里是vs编译器默认的析构函数对此处有优化,它和编译器的实现有关,不是很重要,重要的是这里一定要匹配使用,不要随意匹配,否则任何错误都有可能发生。

相关文章
|
14天前
|
存储 编译器 C语言
内存管理【C++】
内存管理【C++】
33 1
|
28天前
|
存储 编译器 C语言
【C++】C\C++内存管理
【C++】C\C++内存管理
【C++】C\C++内存管理
|
27天前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
8天前
|
C语言 C++
C++(二)内存管理
本文档详细介绍了C++中的内存管理机制,特别是`new`和`delete`关键字的使用方法。首先通过示例代码展示了如何使用`new`和`delete`进行单个变量和数组的内存分配与释放。接着讨论了内存申请失败时的处理方式,包括直接抛出异常、使用`try/catch`捕获异常、设置`set_new_handler`函数以及不抛出异常的处理方式。通过这些方法,可以有效避免内存泄漏和多重释放的问题。
|
29天前
|
存储 Java C语言
【C++】C/C++内存管理
【C++】C/C++内存管理
|
1月前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
57 5
|
22天前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
35 0
|
2月前
|
NoSQL Redis C++
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
|
2月前
|
存储 C语言 C++
【C/C++】动态内存管理( C++:new,delete)
C++的`new`和`delete`用于动态内存管理,分配和释放内存。`new`分配内存并调用构造函数,`delete`释放内存并调用析构函数。`new[]`和`delete[]`分别用于数组分配和释放。不正确匹配可能导致内存泄漏。内置类型分配时不初始化,自定义类型则调用构造/析构。`operator new`和`operator delete`是系统底层的内存管理函数,封装了`malloc`和`free`。定位`new`允许在已分配内存上构造对象,常用于内存池。智能指针等现代C++特性能进一步帮助管理内存。
|
2月前
|
存储 编译器 程序员
【C/C++】动态内存管理(C:malloc,realloc,calloc,free)
探索C++与C语言的动态内存管理:从malloc到new/delete,了解内存分布及栈、堆的区别。文章涵盖malloc、realloc、calloc与free在C中的使用,强调内存泄漏的风险。C++引入new和delete,支持对象构造与析构,还包括operator new和placement-new。深入分析内存管理机制,揭示C与C++在内存处理上的异同。别忘了,正确释放内存至关重要!