文章目录
- 一.C\C++内存分布
- 二.C语言中动态内存管理方式:malloc/calloc/realloc/free
- 三.C++内存管理方式
- [四.operator new与operator delete函数(重要点进行讲解)](#四.operator new与operator delete函数(重要点进行讲解))
-
- [4.1. operator new与operator delete函数(重点)](#4.1. operator new与operator delete函数(重点))
- 五.new和delete的实现原理
-
- 5.1.内置类型
- [5.2 自定义类型](#5.2 自定义类型)
- [六. 定位new表达式(placement-new) (了解)](#六. 定位new表达式(placement-new) (了解))
- [七. 7. 常见面试题](#七. 7. 常见面试题)
-
- [7.1. malloc/free和new/delete的区别](#7.1. malloc/free和new/delete的区别)
- [7.2 内存泄漏](#7.2 内存泄漏)
一.C\C++内存分布
C和C++的内存分布是一样的
为什么要内存区域划分?
为了内存方便管理
下面的划分的区域 堆区是我们重点关注的,因为堆上的空间是由我们开辟和释放的,是由我们控 制的。
看代码回答 问题?
cpp
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);
}
1. 选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
globalVar在哪里?____ staticGlobalVar在哪里?____
staticVar在哪里?____ localVar在哪里?____
num1 在哪里?____
char2在哪里?____
pChar3在哪里?____
ptr1在哪里?____
2. 填空题:
sizeof(num1) = ____;
*char2在哪里?___
*pChar3在哪里?____
*ptr1在哪里?____
sizeof(char2) = ____;
sizeof(pChar3) = ____;
sizeof(ptr1) = ____;
3. sizeof 和 strlen 区别?
strlen(char2) = ____;
strlen(pChar3) = ____;
答案
【说明】
- 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。
- 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口
创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下) - 堆用于程序运行时动态内存分配,堆是可以上增长的。
- 数据段--存储全局数据和静态数据。
- 代码段--可执行的代码/只读常量。
二.C语言中动态内存管理方式:malloc/calloc/realloc/free
cpp
void Test ()
{
int* p1 = (int*) malloc(sizeof(int));
free(p1);
// 1.malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof (int));
int* p3 = (int*)realloc(p2, sizeof(int)*10);
// 这里需要free(p2)吗? 不需要 原地扩容p3 还是p2接收地址 异地扩容 自动free(p2)
free(p3 );
}
【面试题】
- malloc/calloc/realloc的区别?
- malloc的实现原理? glibc中malloc实现原理
三.C++内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因
此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
3.1.new/delete操作内置类型
cpp
void Test()
{
// 动态申请一个int类型的空间
int* ptr4 = new int;
// 动态申请一个int类型的空间并初始化为10
int* ptr5 = new int(10);
// 动态申请10个int类型的空间
int* ptr6 = new int[3];
delete ptr4;
delete ptr5;
delete[] ptr6;
}
cpp
int main()
{
//开辟一个空间
int* ptr = new int;//开辟一共int类型的空间 在堆区 返回一共堆上开辟好的空间地址
//开辟一个空间并且初始化
int* ptr1 = new int(10); //只需要在开辟空间类型中+(初始化值)即可
cout <<"ptr1存放地址对应值:" << *ptr1 << endl;
//开辟多个空间
int* ptr2 = new int[10];//在开辟空间类型后加上+[开辟个数]即可 并返回开辟数组(多个空间)的首地址
//开辟多个空间并且初始化 在之前c++是不允许开辟的数组初始化的 C++11就可以了
int* ptr3 = new int[10] {1, 2, 3, 4, 5};//开辟数组空间 初始化用{里面写初始化值} 可以完全初始化 也可不完全初始化 不完全初始化的空间默认初始化为0
int arr[5] = { 1,2,3,4,5 };
//将开辟好的空间 释放掉
delete(ptr);
delete(ptr1);
delete[](ptr2); //数组的释放 连续的空间释放+delete[] 指针存放地址
delete[](ptr3);
return 0;
}
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。
3.2.new和delete操作自定义类型
cpp
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
}
cout << "~A():" << this << endl;
private:
int _a;
};
int main()
{
// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数
A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A(1);
free(p1);
delete p2;
// 内置类型是几乎是一样的
int* p3 = (int*)malloc(sizeof(int)); // C
int* p4 = new int;
free(p3);
delete p4;
A* p5 = (A*)malloc(sizeof(A)*10);
A* p6 = new A[10];
free(p5);
delete[] p6;
return 0;
}
注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。
new开辟空间失败会抛异常,不需要手动检查
抛异常 捕获异常