当前位置:首页 » 《随便一记》 » 正文

【C++】内存管理

0 人参与  2024年02月20日 15:06  分类 : 《随便一记》  评论

点击全文阅读


在这里插入图片描述

前言:
内存管理


文章目录

一、内存分布二、C和C++中的动态内存管理三、operator new与operator delete函数四、定位 new (了解)五、malloc/free和new/delete的区别

一、内存分布

内存分布通常可以分为以下几个区域:

栈(Stack):栈用于存储局部变量、函数参数和函数返回地址等信息。且向下增长

堆(Heap):堆用于动态分配内存,即通过 newmalloc 等关键字在运行时分配内存。

数据段 (全局/静态存储区 Global/Static Storage Area)全局变量和静态变量在程序启动时被分配在全局/静态存储区域。全局变量在整个程序执行期间都存在,而静态变量具有局部作用域(局部静态变量,例如在函数中声明的静态变量)但生命周期与程序执行期间一样长。全局/静态存储区的内存分配在程序启动时完成,在程序结束时释放。

常量存储区(Constant Storage Area)常量字符串等常量数据存储在常量存储区,其内容在程序运行期间不可改变。常量存储区的内存通常位于程序的可执行文件中,因此称为常量存储区。

代码区(Code Area):**代码区存储程序的机器指令,即可执行代码。**代码区通常位于可执行文件的某个特定部分,在程序执行时被加载到内存中供CPU执行。

我们来看一下这些例子:

int globalVar = 1;//globalVar是全局变量,存在数据段上static int staticGlobalVar = 1;//staticGlobalVar是静态变量,存在数据段上int main(){    static int staticVar = 1;//staticVar局部静态变量,存在数据段上        int localVar = 1;//localVal是局部变量,在栈上        int num1[10] = { 1, 2, 3, 4 };//num1局部变量,在栈上        //char2是数组名,首元素地址,存在栈上;    //*char2,实际上是字符'a'且字符串"abcd"也是在栈中,所以*char2同样存在栈中    char char2[] = "abcd";//pChar3是指针变量,存放在栈中;//因为加了const修饰,所以字符串常量"abcd"存储在常量存储区,只读操作,不可修改;如果没有const修饰,就存在栈中,因此加了const修饰后,*pChar3储存在常量区    const char* pChar3 = "abcd";//ptr1是指针变量,存在栈中;*ptr1是分配的内存,存在堆中    int* ptr1 = (int*)malloc(sizeof(int) * 4);    free(ptr1);}

二、C和C++中的动态内存管理

C 中的动态内存管理

动态内存分配函数:C 中的动态内存分配函数包括 malloc(), calloc(), realloc()。例如:

int* ptr = (int*)malloc(sizeof(int) * 10); // 分配一个包含 10 个整数的内存块

释放动态分配的内存:使用 free() 函数可以释放动态分配的内存,防止内存泄漏。例如:

free(ptr); // 释放动态分配的内存

C++ 中的动态内存管理

动态内存分配运算符:C++ 中使用 new 运算符来动态分配内存。例如:

int* ptr1 = new int(1); // 分配一个整型并初始化int* ptr2 = new int[10]; // 分配一个包含 10 个整数的内存int* ptr3 = new int[5] = {1, 2, 3, 4, 5};// 分配五个整型并初始化

释放动态分配的内存:使用 delete 运算符释放动态分配的内存,与 C 中的 free() 相对应。例如:

// 释放动态分配的内存delete ptr1;delete[] ptr2; delete[] ptr3;

三、operator new与operator delete函数

newdelete是用户进行动态内存申请和释放的操作符,operator newoperator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

operator new operator delete 在大多数系统中,底层会使用 mallocfree来分配或释放内存,但在一些特定的环境中,可能会使用其他的内存分配和释放函数。

在这里插入图片描述

四、定位 new (了解)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

一般的 new 表达式会分配内存并在该内存上构造对象,而定位 new 表达式则允许你提供一个已经分配的内存地址来构造对象。

定位new表达式的基本语法:

new (pointer) Type(initializer)

其中,pointer 是一个指向要构造对象的内存位置的指针,Type 是要构造的对象类型,initializer 是可选的初始化参数。

以下是一个示例,演示了如何使用定位new表达式:

#include <iostream>class MyClass {public:    MyClass(int value) : m_value(value) {        std::cout << "Constructing MyClass with value: " << m_value << std::endl;    }private:    int m_value;};int main() {    // 分配内存    char buffer[sizeof(MyClass)];    // 在给定内存位置上构造对象    MyClass* obj = new (buffer) MyClass(42);        return 0;}

在这里插入图片描述

在这个示例中,我们首先分配了足够大的内存缓冲区(buffer),然后使用定位new表达式在该缓冲区上构造了一个 MyClass 对象。注意,我们在构造对象后,可以像常规指针一样使用该对象。

定位new表达式的一个常见用途是在特定的内存位置上构造对象,比如在实现自定义内存池或者对象池时。


五、malloc/free和new/delete的区别

不同点:

mallocfree 是 C 语言中的函数,而 newdelete 是 C++ 中的操作符。

malloc 分配的内存不会初始化,而 new 可以初始化。但是需要注意,对于内置类型(如 intdouble 等),new 分配的内存并不会被初始化。

malloc 需要手动计算空间大小并传递,而 new 不需要,因为它知道要分配的类型的大小。对于数组,new 可以使用 [] 指定对象个数。

malloc 的返回值是 void*,需要显式转换为目标类型,而 new 返回的是所分配类型的指针,不需要显式转换。

当内存不足时,malloc 返回 NULL,需要检查是否为 NULL,而 new 抛出 std::bad_alloc 异常。

对于自定义类型,mallocfree 只是分配和释放内存,并不会调用构造函数和析构函数。而 new 在分配内存后会调用构造函数初始化对象,delete 在释放内存前会调用析构函数。

共同点:

都用于从堆上申请空间,并且需要用户手动释放。

在这里插入图片描述
如果你喜欢这篇文章,点赞?+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。


点击全文阅读


本文链接:http://zhangshiyu.com/post/69203.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1