C/C++内存管理相关知识点

简介: 1.内存分布C/C++将内存大体上分为四个区域:栈区、堆区、静态区(数据段)、常量区(代码段)。栈区:用来存储函数调用时的临时信息的结构,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。

1.内存分布

C/C++将内存大体上分为四个区域:栈区、堆区、静态区(数据段)、常量区(代码段)。

栈区:用来存储函数调用时的临时信息的结构,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。

堆区:程序员自己使用malloc或new自己申请出来存的地方。(动态内存分配)

静态区: static修饰的数据,全局数据,存放的位置。

常量区:不会改变的常量,存在这里。

看下面一段代码,回答问题:

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
 static int staticVar = 1;
 int localVar = 1;
 int num1[10] = { 1, 2, 3, 4 };
 char char2[] = "abcd";
 const char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof(int) * 4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
 free(ptr1);
 free(ptr3);
}

看上面一段代码,请回答如下:


e665c6e91fed43efaffe240be6f67091.png

b4075d727dfb4300b0d3ecb51e27626a.png

2. new/delete关键字

2.1 操作内置类型

int main()
{
  //动态申请一个int 类型的空间
  int* ptr1 = new int;
  delete ptr1;      //释放ptr1
  // 动态申请一个int 类型的空间,并初始化为 5
  int* ptr2 = new int(5);
  delete ptr2;       //释放ptr2
  // 动态申请5个int 类型的空间
  int* ptr3 = new int[5];
  delete[] ptr3;         // 释放ptr3,注意怎么new的怎么delete
   动态申请5个int 类型的空间,并初始化
  int* ptr4 = new int[5]{ 1,2,3 };
  delete[] ptr4;       // 释放ptr4,注意怎么new的怎么delete
  return 0;
}

**注意:new 对应 delete,new [] 对应 delete [] 。**不可用错。

操作自定义类型

new 和 delete 除了申请和释放空间外,会自动调用构造函数和析构函数。

class A
{
public:
  A(int a = 0)
  {
    cout << "A()" << endl;
  }
  ~A()
  {
    cout << "~A()" << endl;
  }
private:
  int _day;
  int _year;
  int _month;
};
int main()
{
  A* p1 = new A(1);  //一次构造
  delete p1;      //一次析构
  A* p2 = new A[5];  // 五次构造
  delete[] p2;       //五次析构
  return 0;
}


3. opeartor new 与 operator delete函数

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

其中:

operator new:该函数实际通过malloc来申请空间,申请成功直接返回;失败时,尝试执行空间不足应对策略,如果用户对该措施设置了,继续申请空间,否则抛异常。

operator delete:该函数最终是通过free()来释放空间的。


fa73bdb62be7422b9e31880da9c37bf1.png

通过该定义也可以看出,free()其实也是一个重命名,真正的函数名是后面的。

4. new 和 delete 原理

4.1 内置类型

如果申请的是内置类型空间,new和malloc,delete和free基本类似,不同的地方是:new和delete申请和释放的是单个元素空间,new[]和delete[]申请和释放的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

4.2 自定义类型

new的原理

1.调用operator new 申请空间

2.在申请的空间上执行构造函数,完成对象的构造。


delete 原理

1.在空间上执行析构函数,完成对象中资源的清理工作

2.调用operator delete函数释放对象的空间


newT[N] 原理

1.调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请。

2.在申请的空间上执行N次构造函数


delete[] 原理

1.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。

2.调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

如下例子总结:


27237a22bdd64743a110a675d553f709.png

5.定位new表达式(placement-new)

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

使用语法:

new (place_address) type 或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表。

new(p1)A;    //如果A的构造函数有参数,此处需要传参
nwe(p2)A(10);  // 初始化参数为10

6. malloc/free 和 new/delete的区别

共同点:

都是从堆上申请空间,并需要手动释放。

不同点:

malloc和free是函数,new和delete是关键字。

malloc申请的空间不会初始化,new可以调用构造函数完成初始化。

malloc申请空间时,需要手动计算空间大小并传递,new只需在其后面跟上空间的类型即可,如果是多个对象,[]中指定个数即可。

malloc返回值是void*,在使用时必须强转,new不需要,因为new后面跟的是空间类型。

malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是需要捕获异常。

申请自定义类型时,malloc/free 只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成对象空间中资源的清理。

7. 内存泄漏

相关知识后续会继续补充。。。

目录
相关文章
|
10天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
33 4
|
1月前
|
存储 缓存 算法
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
|
1月前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
103 21
|
29天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
存储 C语言 C++
【C++打怪之路Lv6】-- 内存管理
【C++打怪之路Lv6】-- 内存管理
37 0
【C++打怪之路Lv6】-- 内存管理
|
1月前
|
存储 C语言 C++
【C/C++内存管理】——我与C++的不解之缘(六)
【C/C++内存管理】——我与C++的不解之缘(六)
|
1月前
|
C++
C/C++内存管理(下)
C/C++内存管理(下)
46 0
|
1月前
|
存储 Linux C语言
C/C++内存管理(上)
C/C++内存管理(上)
38 0
|
1月前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
47 0
|
8天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
36 4