关于c++:C内存管理

1次阅读

共计 2204 个字符,预计需要花费 6 分钟才能阅读完成。

内存分类

  • 栈区、堆区、动态区、代码段

    • 栈区:用来存储局部变量、函数的形式参数(寄存长期变量)
    • 堆区:动态内存调配
    • 动态区:寄存动态变量、全局变量(程序完结时,才被销毁)
    • 代码段:寄存函数体(类成员函数和全局函数)的二进制代码
    int globalvar = 10;               //globalvar 存储于动态区 (数据段)
    static int stglobalvar = 10;      //stglobalvar 存储于动态区
    int main()
    {
      static int stcavar = 10;      //stcavar 存储于动态区
      int locavar = 10;             //locavar 局部变量,存储于栈
      int num1[10] = {1,2,3,4};   //num1  数组存储于栈
      char char2[] = "abcd";        //char2 存储于栈;*char2 存储于栈
      const char* pchar3 = "abcd";  //pchar3 局部变量指针存储于栈中,*pchar3 存储于代码段中 (常量区)
      int* ptr = (int*)malloc(sizeof(int) * 4); //ptr 局部变量指针存储于栈中;*ptr 开拓的空间,存储于堆中
      free(ptr);
    }

    内存透露

  • 什么是内存透露:因为某种原因导致程序未能开释不再应用的内存。
  • 内存透露不是指物理上的内存隐没,而是指失去了对某段内存的控制权(指针失落)

C++ 动静申请内存 new

  • C++ 语法兼容 C 语言,所以 C 语言的 malloc 和 realloc 等都能够应用。
  • C++ 语法还有新的办法能够动静申请内存空间——new 和 delete
  • 留神:malloc 开拓的空间只能 free,new 开拓的空间只能 delete。
int main()
{int* ptr1 = (int*)malloc(sizeof(int) * 4);
    int* ptr2 = new int[10];     // 开拓多个空间时,应用中括号
    free(ptr1);
    delete[] ptr2;
 
 
    int* ptr3 = (int*)malloc(sizeof(int));
    int* ptr4 = new int;         // 开拓单个空间时
    free(ptr3);
    delete ptr4;
}

malloc 和 new 的区别

  • malloc 和 new 在申请根本类型的空间时,都是一样的,没有区别。
  • 区别:

    • new 在申请自定义类型时,会开拓空间,并调用构造函数进行初始化。
    • malloc 只是开拓空间,而不会进行初始化。
    • delete 是先析构函数清理,再开释空间。
    • free 只是开释空间。
    • malloc 开拓空间失败后返回 NULL,而 new 开拓空间失败会抛异样。
  • 32 位零碎下,new 和 malloc 最多能申请 2G 内存,想申请更大内存能够换成 64 位。
struct List
{
    List* _pre;
    List* _next;
    int _val;
    List(int val = 0)    // 构造函数
        :_pre(nullptr)
        ,_next(nullptr)
        ,_val(val)
    {}};

int main()
{struct List* n1 = (struct List*)malloc(sizeof(struct List));
    List* n2 = new List;
}

operator new 和 operator delete 函数

  • new 和 delete 是零碎提供的操作符,而 operator new 和 operator delete 是零碎提供的全局函数
  • 操作符 new 的底层是通过调用 operator new 来申请空间的。
  • 操作符 delete 的底层是通过调用 operator delete 来开释空间的。

    • new 相当于 operator new + 构造函数
    • delete 相当于 析构函数 + operator delete
    • operator new 相当于 malloc + 失败抛异样机制
    • operator delete 相当于 free
  • operator new 和 operator delete 在性能上和 malloc 和 free 雷同
  • 都只是开拓空间而不会调用构造函数进行初始化。

operator new 和 malloc 的区别

  • 次要区别是:当开拓空间失败后,解决办法不同。

    • operator new 失败后是抛异样
    • malloc 失败后是返回 NULL。
  • 当 try 中运行出现异常后,会立马跳转到 catch 中。
int main()
{struct List* n1 = (struct List*)malloc(0x7fffffff);
    if (n1 == NULL) //malloc 失败返回 NULL
    {cout << "malloc 失败" << endl;}

    try   // 尝试运行下列代码
    {List* n3 = (struct List*)operator new(0x7fffffff);
    }
    catch (const std::exception&e)  //try 运行失败后,捕捉异样
    {cout << e.what() << endl;
    }
}

定位 new(初始化已开拓的空间)

  • 定位 new 是用来在曾经开拓了的空间中,通过调用构造函数来对其进行初始化。
int main()
{List* n1 = (List*)malloc(sizeof(List));  // 开拓空间,但未初始化
    new(n1)List;  // 定位 new 调用构造函数,初始化对象 n

    // 等价于 operator new
    List* n2 = (List*)operator new(sizeof(List));
    new(n2)List;
    // 等价于 delete
    n2->~List();  // 调用析构函数,析构函数是能够显示调用的,然而构造函数不能。operator delete(n2);
}
正文完
 0