学科分类
目录
C++基础

new与delete

在C语言中,动态分配内存时一般常使用malloc()函数,但是对于非内置数据类型(如struct、enum、class等),malloc()与free()无法满足动态对象的需求,因此C++引入new与delete关键字,用来进行内存申请与释放空间。

1、new运算符

new运算符用来申请一块连续的内存,其格式如下:

new 数据类型(初始化列表);

我们知道,malloc()函数申请内存时返回的是一个void*类型的指针,而new与malloc()不同,它分配一块存储空间并且指定了类型信息,并根据初始化列表中给出的值进行初始化,是直接可以使用的内存,这个过程,程序员常称之为new一个对象。而且new动态创建对象时不必为该对象命名,直接指定数据类型即可。如果申请内存成功,返回一个类型指针;如果内存申请失败,则返回NULL。

用new可以创建基本数据类型对象,示例代码如下:

char *pc = new char;         //申请一段空间用来存储char类型,内存中没有初始值
int *pi = new int(10);       //申请一段空间存储int类型数据,初始值为10
double *pd = new double();   //申请一段空间存储double类型的数据,默认初始值为0

上述代码分别用new创建了char、int、double三个对象,其中char对象没有初始化列表,新分配内存中没有初始值;int对象初始化列表为10,是分配一个空间存储int类型数据,并把10存入该空间;double对象初始化列表为空,表示用0初始化该对象。

new也可以用来创建数组对象,其格式如下:

new 数据类型[数组长度];

new数组时,后面可以加小括号(),但括号中不可以有指定任何初始值,加小括号时由编译器为其提供默认初始值,而不加小括号时不提供任何初始值。例如:

int *pi = new int[10]();
char *pc = new char[10];
double* pd = new double[0];

pi所指向的数组中10个元素初始化为0,pc所指向的数组中没有提供初始值。而pd是一个长度为0的dobule类型数组,C++虽然不允许定义长度为0的数组变量,但明确指出,调用new创建长度为0的数组是合法的,它返回有效的非零指针,但该指针不能进行有效的解引用操作,因为它没有指向任何元素,它主要的作用是用于比较运算。

除上述数组创建外,new还可以创建const对象的动态数组,但const对象数组一经创建就不允许更改,因此意义不大,读者只需知道其事即可。

2、delete运算符

用new运算符分配内存,使用后要及时释放以免造成内存泄露,C++提供了delete运算符来释放new出来的内存空间,其格式如下:

delete 指针名;

直接作用于指针就可以删除由new创建的对象,释放指针所指向的内存空间。但在释放数组对象时要在指针名前加上[],其格式如下:

delete []指针名;

​ 如果漏掉了[],编译器在编译时无法发现错误,但它会导致少释放内存空间,产生内存泄露严重时会产生运行错误等。

学习完了new与delete运算符,接下来就通过一个案例来加深读者的理解与使用,如例1所示。

例1

 1    #include <iostream>
 2    using namespace std;
 3    int main()
 4    {
 5        int *pi = new int(10); //new 一个int对象,初始值为10
 6        cout << "*pi = " << *pi << endl;
 7        *pi = 20;    //通过指针改变变量的值
 8        cout << "*pi = " << *pi << endl;
 9        char *pc = new char[10];
 10        for (int i = 0; i < 10; i++)
 11            pc[i] = i + 65;    //向数组中存入元素
 12        for (int i = 0; i < 10; i++)
 13            cout << pc[i] << " ";
 14        cout << endl;
 15        delete pi;      //释放int对象
 16        delete []pc;    //释放数组对象
 17         system("pause");
 18        return 0;
 19    }

运行结果如图1所示。

图1 例1运行结果

例1中分别创建了一个int对象和一个char类型数组对象,int对象初始化值为10,通过指针可以修改其值,char数组对象没有初始化,案例中通过下标法为数组赋值。注意在使用完new对象之后一定要用delete释放内存。

多学一招:new/delete与malloc()/free()

malloc()/free()是C语言的标准库函数,new/delete是C++的运算符,它们都可用于申请动态内存和释放内存,new/delete在实现上其实调用了malloc()/free()函数,然后又做了一些其他封装,所以两者虽有相似却又有不同。1、new创建对象时返回的是直接带类型信息的指针,而malloc()返回的都是void*类型的指针。

2、两者在创建对象时都可能造成内存泄露,但new可以定位到哪个文件的哪一行,而malloc()没有这些信息。

3、对于非内置类型对象而言,new/delete在创建对象时不止是分配内存,还会自动执行构造函数进行初始化,对象消亡之前自动执行析构函数,而malloc()/free()只能简单的分配释放内存。

4、new与malloc()申请内存位置不同,new从自由存储区(free store)分配,而malloc()从堆区(heap)分配(请参考ISO14882内存管理部分),free store和heap很相似,都是动态内存,但位置不同,这就是为什么new出来的内存不能通过free()释放。但大部分编译器并没有很好的执行这一条标准,很有可能把free store和heap混淆起来,因此有时使用free()释放new出来的对象也不会报错,但这会造成程序的可读性差,所以还是要各自配对使用。

在C++程序中完全可以用new/delete来代替malloc()/free(),但C++程序经常要调用C函数,而C程序只能用malloc()/free()来管理内存,为了保持与C兼容,所以在C++中把malloc()/free()也保留了下来。

点击此处
隐藏目录