当前位置:   article > 正文

c++(内存管理)_c++内存管理

c++内存管理

目录

一.c++内存分布

二.c++内存管理方式

三.operator new与operator delete函数

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

五.定位new表达式(placement-new)(构造函数)


一.c++内存分布

1. 又叫堆栈 -- 非静态局部变量 / 函数参数 / 返回值等等,栈是向下增长的。
2. 内存映射段 是高效的 I/O 映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信
3. 用于程序运行时动态内存分配,堆是可以上增长的。
4. 数据段 -- 存储全局数据和静态数据。
5. 代码段 -- 可执行的代码 / 只读常量。

二.c++内存管理方式

自定义类型调用构造函数和析构函数 

抛异常用try/catch

三.operator newoperator delete函数

1.内置类型:

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

2.自定义类型:
new的原理
1. 调用 operator new 函数申请空间(底层用malloc实现的)
2. 在申请的空间上执行构造函数,完成对象的构造
delete的原理
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用 operator delete 函数释放对象的空间(free)
new T[N]的原理
1. 调用 operator new[] 函数,在 operator new[] 中实际调用 operator new 函数完成 N 个对象空间的申请
2. 在申请的空间上执行 N 次构造函数
delete[]的原理
1. 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理
2. 调用 operator delete[] 释放空间,实际在 operator delete[] 中调用 operator delete 来释放空间

  1. #include"iostream"
  2. using namespace std;
  3. int main()
  4. {
  5. int* p1 = new int;
  6. free(p1);//内置类型用free与new配套不会造成内存泄漏
  7. return 0;
  8. }
  1. #include"iostream"
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. A(int a1 = 0, int a2 = 0)
  7. :_a1(a1)
  8. , _a2(a2)
  9. {
  10. cout << "A(int a1 = 0, int a2 = 0)" << endl;
  11. }
  12. A(const A& aa)
  13. :_a1(aa._a1)
  14. {
  15. cout << "A(const A& aa)" << endl;
  16. }
  17. A& operator=(const A& aa)
  18. {
  19. cout << "A& operator=(const A& aa)" << endl;
  20. if (this != &aa)
  21. {
  22. _a1 = aa._a1;
  23. }
  24. return *this;
  25. }
  26. ~A()
  27. {
  28. //delete _ptr;
  29. cout << "~A()" << endl;
  30. }
  31. void Print()
  32. {
  33. cout << "A::Print->" << _a1 << endl;
  34. }
  35. A& operator++()
  36. {
  37. _a1 += 100;
  38. return *this;
  39. }
  40. private:
  41. int _a1 = 1;
  42. int _a2 = 1;
  43. };
  44. int main()
  45. {
  46. A* p1 = new A;
  47. free(p1);//自定义类型,析构函数中没有释放资源,也不会造成内存泄漏
  48. return 0;
  49. }
  1. #include"iostream"
  2. using namespace std;
  3. int main()
  4. {
  5. int* p1 = new int[10];
  6. delete p1;//不报错
  7. return 0;
  8. }
  1. class A
  2. {
  3. public:
  4. A(int a1 = 0, int a2 = 0)
  5. :_a1(a1)
  6. , _a2(a2)
  7. {
  8. cout << "A(int a1 = 0, int a2 = 0)" << endl;
  9. }
  10. A(const A& aa)
  11. :_a1(aa._a1)
  12. {
  13. cout << "A(const A& aa)" << endl;
  14. }
  15. A& operator=(const A& aa)
  16. {
  17. cout << "A& operator=(const A& aa)" << endl;
  18. if (this != &aa)
  19. {
  20. _a1 = aa._a1;
  21. }
  22. return *this;
  23. }
  24. ~A()
  25. {
  26. //delete _ptr;
  27. cout << "~A()" << endl;
  28. }
  29. void Print()
  30. {
  31. cout << "A::Print->" << _a1 << endl;
  32. }
  33. A& operator++()
  34. {
  35. _a1 += 100;
  36. return *this;
  37. }
  38. private:
  39. int _a1 = 1;
  40. int _a2 = 1;
  41. };
  42. class B
  43. {
  44. public:
  45. /*~B()
  46. {
  47. cout << "~B()" << endl;
  48. }*/
  49. private:
  50. int _b1 = 2;
  51. int _b2 = 2;
  52. };
  53. #include"iostream"
  54. using namespace std;
  55. int main()
  56. {
  57. A* p1 = new A[10];
  58. delete p1;//由于A类有析构函数,所以编译器会开四个字节存放要析构的个数,但是仅释放80个字节的空间,故由于不能从中间释放,所以系统崩溃
  59. B* p2 = new B[10];
  60. delete p2;//由于B类没有析构函数,不会再开头开4个字节的空间,故从头释放,不会崩溃
  61. return 0;
  62. }

四.malloc/freenew/delete的区别

malloc/free new/delete 的共同点是:都是从上申请空间,并且需要用户手动释放。不同的地方是:
1. malloc free 是函数, new delete 是操作符
2. malloc 申请的空间不会初始化, new 可以初始化
3. malloc 申请空间时,需要手动计算空间大小并传递, new 只需在其后跟上空间的类型即可, 如果是多个
对象, [] 中指定对象个数即可
4. malloc 的返回值为 void*, 在使用时必须强转, new 不需要,因为 new 后跟的是空间的类型
5. malloc 申请空间失败时,返回的是 NULL ,因此使用时必须判空, new 不需要,但是 new 需要捕获异常
6. 申请自定义类型对象时, malloc/free 只会开辟空间,不会调用构造函数与析构函数,而 new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

五.定位new表达式(placement-new)(构造函数)

定位 new 表达式是在 已分配的原始内存空间中调用构造函数初始化一个对象
使用格式:
new (place_address) type 或者 new (place_address) type(initializer-list)
place_address 必须是一个指针, initializer-list 是类型的初始化列表

使用场景:
定位 new 表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new 的定义表达式进行显示调构造函数进行初始化
  1. class A
  2. {
  3. public:
  4. A(int a1 = 0, int a2 = 0)
  5. :_a1(a1)
  6. , _a2(a2)
  7. {
  8. cout << "A(int a1 = 0, int a2 = 0)" << endl;
  9. }
  10. A(const A& aa)
  11. :_a1(aa._a1)
  12. {
  13. cout << "A(const A& aa)" << endl;
  14. }
  15. A& operator=(const A& aa)
  16. {
  17. cout << "A& operator=(const A& aa)" << endl;
  18. if (this != &aa)
  19. {
  20. _a1 = aa._a1;
  21. }
  22. return *this;
  23. }
  24. ~A()
  25. {
  26. //delete _ptr;
  27. cout << "~A()" << endl;
  28. }
  29. void Print()
  30. {
  31. cout << "A::Print->" << _a1 << endl;
  32. }
  33. A& operator++()
  34. {
  35. _a1 += 100;
  36. return *this;
  37. }
  38. private:
  39. int _a1 = 1;
  40. int _a2 = 1;
  41. };
  42. #include"iostream"
  43. using namespace std;
  44. int main()
  45. {
  46. A* p1 = new A(1);
  47. delete p1;
  48. A* p2 = (A*)operator new(sizeof(A));
  49. new(p2)A(1);
  50. p2->~A();
  51. operator delete(p2);
  52. return 0;
  53. }

内存池(池化技术--》提高性能) 高频申请释放内存块(仅申请了空间,要调用operator new初始化)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/1015221
推荐阅读
相关标签
  

闽ICP备14008679号