C++中的delete和delete[ ]的区别

本文解析了使用new和delete操作符在C++中分配和释放内存的不同场景,特别是对于基本数据类型和自定义数据类型(如类)的区别。强调了在数组分配时使用new[]与释放时使用delete[]的重要性,避免析构函数未被正确调用导致的资源泄露问题。

以前看书的时候,书上说使用new申请的内存,释放时用delete,使用new [ ]申请的内存释放时要用delete [ ]才行,这两个一定要记住,申请时用了方括号,则释放时也要加上方括号,否则就会出错。但是并没有解释为什么这样,会出什么错。今天正好看到这个,记录下。

关于动态申请的内存,分两种情况:基本数据类型的分配和自定义数据类型的分配。两者不同。

1、基本数据类型

对于基本数据类型,假如有如下代码

int *a = new int[10];
.......
delete a;        //方式1
delete [] a;     //方式2

肯定会不少人认为方式1存在内存泄露,然而事实上是不会!针对简单的基本数据类型,方式1和方式2均可正常工作,因为:基本的数据类型对象没有析构函数,并且new 在分配内存时会记录分配的空间大小,则delete时能正确释放内存,无需调用析构函数释放其余指针。因此两种方式均可。

2、自定义数据类型

这里一般指类,假设通过new申请了一个对象数组,注意是对象数组,返回一个指针,对于此对象数组的内存释放,需要做两件事情:一是释放最初申请的那部分空间,二是调用析构函数完成清理工作。对于内存空间的清理,由于申请时记录了其大小,因此无论使用delete还是delete[]都能将这片空间完整释放,而问题就出再析构函数的调用上,当使用delete时,仅仅调用了对象数组中第一个对象的析构函数,而使用delete[]的话,将会逐个调用析构函数。
在这里插入图片描述
有如下代码:

#include <iostream>

using namespace std;

class T{
public:
    T(){cout << "constructor" << endl;}
    ~T(){cout << "destructor" << endl;}
};

int main(int argc,char **argv)
{
    const int NUM = 3;
    T* p1 = new T[NUM];
    cout << p1 << endl;
    delete p1;

    cout << endl;
    
    T* p2 = new T[NUM];
    cout << p2 << endl;
    delete [] p2;

    return 0;
}

输出结果为:
在这里插入图片描述
在这里插入图片描述
可以看到,不加[ ]符号确实只调用了一次析构函数。

问题来了,既然不加方括号也能完整释放内存,那不就没多调用几个析构函数吗,怎么了?想想看,万一析构函数需要释放系统资源呢?比如文件?线程?端口?这些东西使用了而不释放将会造成严重的后果。因此,虽然内存完整的释放了,但是有时候不调用析构函数则会造成潜在的危险。

所以,new的时候使用了[ ],那么delete的时候还是使用[ ]吧!

### C++ 中 `delete` `delete[]` 的区别C++ 编程语言中,动态内存分配是一个重要的概念。为了有效地管理释放这些资源,C++ 提供了两个操作符:`delete` `delete[]`。 #### 单一对象的删除 (`delete`) 当通过 `new` 关键字为单一对象分配内存时,应使用 `delete` 来释放该内存。这不仅会释放分配给对象的空间,还会调用对象的析构函数来执行清理工作[^3]。如果尝试使用 `free()` 而不是 `delete`,则不会触发析构函数的行为,从而可能导致未定义行为或资源泄漏。 ```cpp MyClass* obj = new MyClass(); // 使用obj... delete obj; // 正确方式,调用了析构函数并释放内存 ``` #### 数组对象的删除 (`delete[]`) 对于通过 `new[]` 创建的对象数组而言,则需采用 `delete[]` 形式来进行销毁。这是因为每一个单独元素都需要被适当地解构;即每项都必须经历一次对应的析构过程以确保所有成员变量得到妥善处理[^5]。如果没有指定 `[ ]` 符号仅运用普通的 `delete` ,程序可能无法正确地遍历整个数组并对每个实例分别应用各自的终止逻辑,进而引发潜在错误甚至崩溃风险。 ```cpp MyClass* arr = new MyClass[10]; // 使用arr... delete[] arr; // 正确方式,逐个调用每个元素的析构函数后再释放整体存储区域 ``` 值得注意的是,在现代C++实践中推荐尽可能依赖智能指针(如unique_ptr 或 shared_ptr)以及容器类(像std::vector),它们能够自动管理生命周期内的资源回收问题,减少手动干预带来的失误几率。 ### 总结对比表 | 特性 | `delete` | `delete[]` | |--------------------|-----------------------------------|------------------------------------| | **适用场景** | 单独对象 | 对象数组 | | **析构调用次数** | 一次 | 等于数组长度 | 以上就是关于两者之间主要差异性的阐述说明。 ```cpp #include <iostream> using namespace std; class Test { public: ~Test(){ cout << "Destructor called\n"; } }; int main () { Test *singleObj = new Test; delete singleObj; Test *arrayOfObjs = new Test[3]; delete [] arrayOfObjs; return 0; } ``` 上述例子展示了如何恰当利用这两个关键字完成各自的任务需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值