

💗博主介绍:计算机专业的一枚大学生 来自重庆 @燃于AC之乐✌专注于C++技术栈,算法,竞赛领域,技术学习和项目实战✌💗
💗根据博主的学习进度更新(可能不及时)
💗后续更新主要内容:C语言,数据结构,C++、linux(系统编程和网络编程)、MySQL、Redis、QT、Python、Git、爬虫、数据可视化、小程序、AI大模型接入,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);
}
- 选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
globalVar在哪里?C
staticGlobalVar在哪里?C
staticVar在哪里?C
localVar在哪里?A
num1 在哪里?A
char2在哪里?A
*char2在哪里?A
pChar3在哪里?A //栈上的局部变量指针
*pChar3在哪里?D //解引用,常量区存的字符串
ptr1在哪里?A //栈上的局部变量指针
*ptr1在哪里?B //解引用,堆
说明
1.栈,--堆栈,非静态局部变量/函数参数/返回值等,向下增长;
2.对,程序运行时动态内存分配,可以向上增长;
3.数据段,存储全局数据和静态数据;
4.代码段,可执行的代码/只读常量;
5.内存映射段:高效的I/O,用于装载一个共享的动态内存库,用户可使用系统接口
创建共享共享内存,做进程间通信。
C++内存管理方式;
通过new和delete操作符进行动态内存管理。注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。
重点:
内置类型
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
自定义类型
new的原理
-
调用operator new函数申请空间;
-
在申请的空间上执行构造函数,完成对象的构造。
delete的原理
-
在空间上执行析构函数,完成对象中资源的清理工作;
-
调用operator delete函数释放对象的空间。
new T[N]的原理
-
调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请;
-
在申请的空间上执行N次构造函数。
delete[]的原理
-
在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2.调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。
注意:new和delete一定要搭配使用,否则可能会有内存泄漏等各种问题。
注意问题:
cpp
#include<iostream>
using namespace std;
class A
{
public:
A(int a1 = 0, int a2 = 0)
:_a1(a1)
, _a2(a2)
{
cout << "A(int a1 = 0, int a2 = 0)" << endl;
}
A(const A& aa)
:_a1(aa._a1)
{
cout << "A(const A& aa)" << endl;
}
A& operator=(const A& aa)
{
cout << "A& operator=(const A& aa)" << endl;
if (this != &aa)
{
_a1 = aa._a1;
}
return *this;
}
~A()
{
//delete _ptr;
cout << "~A()" << endl;
}
void Print()
{
cout << "A::Print->" << _a1 << endl;
}
A& operator++()
{
_a1 += 100;
return *this;
}
private:
int _a1 = 1;
int _a2 = 1;
};
class B
{
public:
/*~B()
{
cout << "~B()" << endl;
}*/
private:
int _b1 = 2;
int _b2 = 2;
};
int main()
{
//内置类型
//int* p1 = new int[10]; // -> malloc
//delete p1; // -> free
//free(p1); //可以
//但是有些情况,析构函数如果有指针释放,可能会有内存泄漏的风险
//自定义类型
B* p2 = new B[10];
delete p2;//没有析构函数不会崩溃,编译器优化,有就会崩溃
//原本是会在原有基础(80Byte)多申请4Byte,用于存大小,给析构函数,delete是从头开始释放内存
//没有析构函数,就不会有前面
//A* p3 = new A[10];
//delete[] p3;//程序会崩溃
return 0;
}
定位new
表达式(placement-new)
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:
new (place_address) type 或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如
果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。
在内存池申请空间,而不是一直在堆(内存)上频繁申请,注意效率更高。

加油!志同道合的人会看到同一片风景。
看到这里请点个赞 ,关注 ,如果觉得有用就收藏一下吧。后续还会持续更新的。 创作不易,还请多多支持!