C++(二)内存管理

简介: 本文档详细介绍了C++中的内存管理机制,特别是`new`和`delete`关键字的使用方法。首先通过示例代码展示了如何使用`new`和`delete`进行单个变量和数组的内存分配与释放。接着讨论了内存申请失败时的处理方式,包括直接抛出异常、使用`try/catch`捕获异常、设置`set_new_handler`函数以及不抛出异常的处理方式。通过这些方法,可以有效避免内存泄漏和多重释放的问题。

c 语言中提供了 malloc 和 free 两个系统函数,完成对堆内存的申请和释放。而 c++则
提供了两关键字 new 和 delete ;

new/delete

new/new[]用法:

int *p = new int; //开辟大小为 sizeof(int)空间

int *a = new int(5); //开辟大小为 sizeof(int)空间,并初始化为 5

// todo new/delete

#include <iostream> //<iostream>
using namespace std; //
int main() {

    //单变量
    int *p=new int(20);
    cout<<*p<<endl; //20
    *p=10;
    cout<<*p<<endl; //10

    string *s=new string("hello");
    cout<<*s<<endl; //hello
    *s="world";
    cout<<*s<<endl; //world


    struct Sut{
        int age;
        string name;
    };
    Sut* s1=new Sut;
    s1->age=20;
    s1->name="Tom";
    cout<<s1->age<<endl; //20
    cout<<s1->name<<endl; //Tom


    Sut* s2=new Sut{10,"Jerry"};
    cout<<s2->age<<endl; //10
    cout<<s2->name<<endl; //Jerry

    delete s2;
    delete s1;
    delete p;
    delete s;
    return 0;
}

多变量空间:


int main() {
     //多变量
     //一维数组
     char* p= new char[40]; //分配40个字节的内存
     memset(p,0,40); //将内存块全部初始化为0
     strcpy(p,"hello world");
     cout<<p<<endl;//hello world

     int *pi=new int[5]{0};//分配5个int类型的内存,并初始化为0
     pi[0]=10;
     for(int i=0;i<5;i++){
         cout<<pi[i]<<" "; //10 0 0 0 0
     }

    char **ppc=new char *[5]{NULL};
    ppc[0]="qqq";
    ppc[1]="www";
    ppc[2]="eee";

    ppc[3]=new char[10];
    strcpy(ppc[3],"xxxxx");
    cout<<endl;

    while(*ppc) {
        cout<<*ppc++<<" "; //qqq www eee xxxxx
    }
    cout<<endl;

    //多维数组
    int (*q)[3] = new int[2][3];
    for(int i=0; i<2; i++)
    {
        for(int j=0; j<3; j++)
        {
            q[i][j] = i+j;
        }
    }
    for(int i=0; i<2; i++)
    {
        for(int j=0; j<3; j++)
        {
            cout<<q[i][j]<<" ";
        }
        cout<<endl;
    }

    int (*qq)[3][4] = new int [2][3][4];


    delete[] qq; //释放内存
    delete[] q; //释放内存
    delete[] ppc[3]; //释放内存
    delete[] ppc; //释放内存
    delete[] pi; //释放内存
    delete[] p; //释放内存
}

new/delete 是关键字,效率高于 malloc 和 free.

配对使用,避免内存泄漏和多重释放。

避免,交叉使用。比如 malloc 申请的空间去 delete,new 出的空间被 free;

new/delete 关键字,重点用在类对像的申请与释放。申请的时候会调用构造器完成初始化,释
放的时候,会调用析构器完成内存的清理。

返回值判断

内存申请失败

int main()
{
    double * pd[50];
    for(int i=0; i<50; i++)
    {
        pd[i] = new double[50000000];
        cout<<i<<endl;
    }
return 0;
}

直接抛出异常,结束程序:

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

try/catch 捕获异常


int main()
{
    double * pd[50];

    try {
        for(int i=0; i<50; i++)
        {
            pd[i] = new double[50000000];

            cout<<i<<endl;
        }
    }catch (std::bad_alloc & e){
        cout<<"内存分配失败: "<<e.what()<<endl;
    }

    cout<<"程序结束"<<endl;



    return 0;
}
内存分配失败: std::bad_alloc
程序结束

set_new_handler


void newErr()
{
    cout<<"new error"<<endl;
    exit(-1);
}

int main()
{
    double * pd[50];
    //set_new_handler 是用来设置一个新的内存分配函数的,当内存分配失败时,会调用这个函数。
    set_new_handler(newErr);

    for(int i=0; i<50; i++)
    {
        pd[i] = new double[50000000];

        cout<<i<<endl;
    }

    cout<<"程序结束"<<endl;



    return 0;
}

输出:
new error

不会抛出异常处理方式

int main()
{
    double * pd[50];
    //set_new_handler 是用来设置一个新的内存分配函数的,当内存分配失败时,会调用这个函数。
    //set_new_handler(newErr);

    for(int i=0; i<50; i++)
    {
        //(nothrow)设置异常处理,如果内存分配失败,不会抛出异常,而是返回nullptr
        pd[i] = new (nothrow)double[50000000];
        if(pd[i] == nullptr){
            cout<<"分配内存失败:"<<__FILE__<<" "<<__func__ <<" "<<__LINE__<<endl;
            exit(-1);
        }

    }
    cout<<"程序结束"<<endl;
    return 0;
}
相关文章
|
21天前
|
存储 编译器 C语言
内存管理【C++】
内存管理【C++】
35 1
|
1月前
|
存储 编译器 C语言
【C++】C\C++内存管理
【C++】C\C++内存管理
【C++】C\C++内存管理
|
1月前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
1月前
|
存储 Java C语言
【C++】C/C++内存管理
【C++】C/C++内存管理
|
1月前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
60 5
|
29天前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
37 0
|
2月前
|
NoSQL Redis C++
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
|
2月前
|
存储 C语言 C++
【C/C++】动态内存管理( C++:new,delete)
C++的`new`和`delete`用于动态内存管理,分配和释放内存。`new`分配内存并调用构造函数,`delete`释放内存并调用析构函数。`new[]`和`delete[]`分别用于数组分配和释放。不正确匹配可能导致内存泄漏。内置类型分配时不初始化,自定义类型则调用构造/析构。`operator new`和`operator delete`是系统底层的内存管理函数,封装了`malloc`和`free`。定位`new`允许在已分配内存上构造对象,常用于内存池。智能指针等现代C++特性能进一步帮助管理内存。
|
2月前
|
存储 编译器 程序员
【C/C++】动态内存管理(C:malloc,realloc,calloc,free)
探索C++与C语言的动态内存管理:从malloc到new/delete,了解内存分布及栈、堆的区别。文章涵盖malloc、realloc、calloc与free在C中的使用,强调内存泄漏的风险。C++引入new和delete,支持对象构造与析构,还包括operator new和placement-new。深入分析内存管理机制,揭示C与C++在内存处理上的异同。别忘了,正确释放内存至关重要!
|
2月前
|
安全 算法 编译器
C++一分钟之-内存模型与数据竞争
【7月更文挑战第10天】了解C++11内存模型对多线程编程至关重要。它定义了线程间同步规则,包括顺序一致性、原子操作和内存屏障。数据竞争可能导致不确定行为,如脏读和丢失更新。可通过互斥量、原子操作和无锁编程避免竞争。示例展示了`std::mutex`和`std::atomic`的使用。掌握内存模型规则,有效防止数据竞争,确保多线程安全和性能。
39 0