指针 delete 删除的是它指向的那部分空间

C++指针与delete操作详解
本文深入探讨了C++中指针的delete操作,解释了delete仅释放指针所指向的内存而非指针自身,以及不当使用可能导致的问题,如野指针和重复释放。并提供了安全使用delete的建议。
转自romanten https://www.cnblogs.com/romanten/p/6885216.html
侵权删除 打扰了
蛮不错的、
说白了就是删除的是 指针原本所指的那部分内存而已 指针还可以使用 但是避免野指针
***

## 指针p的delete:

***
p所指的空间。
比如 int* p = new int(1);
delete p;
就会在堆上分配一块内存,当作int类型使用,并赋值为1,将其地址储存在栈上的int*类型的p里。delete p会释放p所指向的内存。而这里p为一自动变量,其本身在程序退出其作用域时销毁。

用delete命令处理某个指针,说是把那个指针删除了是不正确的。

delete命令指示释放了那个指针原本所指的那部分内存而已。被delete后的指针p的值(地址值)并非就是NULL,而是随机值。

也就是被delete后,如果不再加上一句p=NULL,p就成了“野指针”,在内存里乱指一通。

如果在定义p的那个函数在delete了p后,没再调用p,就没什么问题,在这个函数结束后,p就会跟其它变量一样被消除。但若在那个函数里delete了p后,又没再给p赋值(地址值),再次调用p就危险了,因为这时p在内存里乱指,有可能指到一些重要地址,随时可能系统崩溃。

//p=NULL是个好习惯

    //就像你蹲完厕所要洗手一样

《问题》危险的代码:

   int* p=new int(1);
   delete p;
   delete p;

 

探讨一:

   连续两次对同一个指针delete ,会造成严重的错误。编译器会检测出这样的错误吗?或许一些编译器会的,但别太过指望编译器。

 

探讨二:

   第一次delete后,p自动为空(NULL)了吗?不是的。

 

探讨三:

   在delete之前会自动检查p是否为空(NULL),如果为空(NULL)就不再delete了吗?确实是如此。

 

探讨四:

   删除为空(NULL)的指针是不会有任何问题的吗?确实是如此。

 

探讨五:

   #define SAFE_DELETE(p) delete (p); p = 0;

   这样就就万事大吉了吗?好像不是的。

   delete p+1;//在C++中是正确的

   SAFE_DELETE(p+1)将会导致错误

 

探讨六:

   没有好的方法解决重复释放这样的问题,只能靠程序员的细心了。

 

《结论》安全的代码:

   int* p=new int(1);
   delete p;
   p = NULL;

(1)delete 一次以后,p成了野指针,它作为地址的值还是有效地没还可以访问它以前指向的内存,不过那片内存被重新格式化了;
(2)p不等于NULL,用 if(p) 语句不能判断它指向的内存是否有效(此时它指向的内存无效,p本身有效);
(3)delete 一次以后,不能再次delete,否则会报错;
(4)此时如果误用p指针,仍然可以修改内存的值和从该处取出数值,但此时数据不受保护,该内存空间可能被重新被分配给别的变量;
(5)如果p指向的空间再次被new函数分配,即使是分配给别的指针,即使分配大小与原来不一样,p又恢复了效力,可以改变内存的值,甚至可以重新被delete,p的作用与新分配的指针一样;
<think> 我们正在讨论如何删除指针指向空间(堆内存)。根据引用[1]中的内容,在C++中,使用`new`运算符在堆上分配的内存必须显式释放,否则会导致内存泄漏。释放内存的方法是使用`delete`运算符。 关键点: 1. 使用`delete`运算符释放指针指向的内存。 2. 释放后,该指针成为悬垂指针(dangling pointer),为了避免误用,通常将指针置为`nullptr`。 3. 每个`new`分配的内存都应该对应一个`delete`。 步骤: 1. 确定指针指向的内存是通过`new`分配的(堆内存)。 2. 使用`delete`释放该内存。 3. 将指针置为`nullptr`(可选,但推荐)。 示例: ```cpp int* p = new int(10); // 动态分配一个int,初始化为10 // 使用p... delete p; // 释放p指向的内存 p = nullptr; // 避免悬垂指针 ``` 注意事项: - 不能对同一个指针重复调用`delete`(会导致未定义行为)。 - 不要释放栈上的内存(例如,不要对指向局部变量指针使用`delete`)。 - 对于数组,使用`delete[]`而不是`delete`。 数组示例: ```cpp int* arr = new int[10]; // 动态分配10个int的数组 // 使用arr... delete[] arr; // 释放数组 arr = nullptr; ``` 引用[2]解释了指针本身的空间指针指向空间的区别。当我们使用`delete`时,我们释放的是指针指向空间(房间),而指针变量本身所占用的空间(门牌号)会在指针变量离开作用域时自动释放(如果是局部变量)。因此,我们主要关注指针指向的堆内存的释放。 引用[3]强调了指针是内存管理工具,每一块内存都有一个地址,指针通过地址来读写内存。因此,正确释放内存是防止内存泄漏的关键。 引用[5]展示了使用`malloc`和`realloc`分配的内存,在C++中,我们通常使用`new`和`delete`,但如果是用`malloc`分配的内存,则应该使用`free`释放。注意:不要混用,即不要用`delete`释放`malloc`分配的内存,也不要用`free`释放`new`分配的内存。 总结: 1. 使用`delete`释放通过`new`分配的单个对象。 2. 使用`delete[]`释放通过`new[]`分配的数组。 3. 释放后将指针置为`nullptr`(避免悬垂指针)。 4. 不要对非堆内存使用`delete`。 5. 确保每个`new`都有对应的`delete`。 相关问题: 1. 如何避免多次释放同一块内存? 2. 什么是悬垂指针?如何避免? 3. 在C++中,智能指针如何帮助自动管理内存释放? </think> ### 如何删除指针指向的堆空间 在C++中删除指针指向的堆空间需严格遵循**内存管理原则**,避免内存泄漏和悬空指针。以下是详细步骤和注意事项: #### 1. **删除单个对象** 使用`delete`释放`new`分配的单个对象: ```cpp int* ptr = new int(42); // 在堆上分配int类型空间 // ...使用ptr... delete ptr; // ✅ 释放指针指向空间 ptr = nullptr; // 推荐置空,避免悬空指针 ``` - **关键点**: - `delete`释放的是指针指向的**堆空间**,指针变量本身(栈空间)由系统自动回收[^2][^3] - 删除后必须立即置空指针,防止野指针访问(`delete`只释放内存,不修改指针值)[^1] #### 2. **删除对象数组** 使用`delete[]`释放`new[]`分配的数组: ```cpp int* arr = new int[10]; // 分配10个int的堆数组 // ...使用arr... delete[] arr; // ✅ 释放整个数组空间 arr = nullptr; ``` - **错误示例**: ```cpp delete arr; // ❌ 错误!仅释放首个元素,内存泄漏 ``` #### 3. **多维数组的删除** 需按维度逆序释放: ```cpp int** matrix = new int*[5]; // 分配5行 for (int i=0; i<5; ++i) { matrix[i] = new int[10]; // 每行分配10列 } // 释放:先释放每行,再释放行指针数组 for (int i=0; i<5; ++i) { delete[] matrix[i]; // 释放第i行 } delete[] matrix; // 释放行指针数组 matrix = nullptr; ``` #### 4. **智能指针自动管理(推荐)** 使用`std::unique_ptr`或`std::shared_ptr`避免手动`delete`: ```cpp #include <memory> // 自动释放单个对象 std::unique_ptr<int> p1(new int(100)); // 自动释放数组(C++14+) std::unique_ptr<int[]> p2(new int[20]); ``` - **优势**: - 离开作用域时自动调用`delete`/`delete[]`[^1] - 禁止拷贝(`unique_ptr`)或引用计数(`shared_ptr`),防止重复释放 #### 5. **关键注意事项** | 情景 | 正确操作 | 风险 | |-----------------------|----------------------------|--------------------------| | **重复删除** | `delete`后立即置空指针 | 未定义行为(程序崩溃)[^1] | | **删除栈内存** | 禁止对栈地址使用`delete` | 破坏运行时堆栈 | | **混合使用new/malloc**| `new`配`delete`,`malloc`配`free` | 跨分配器释放导致崩溃 | | **删除不完整类型** | 确保类型定义可见 | 未调用析构函数,资源泄漏 | #### 内存操作原理 $$ \begin{cases} \text{指针变量空间} & : \text{固定大小(如8字节)} \\ \text{指向的堆空间} & : \text{由new分配的大小(如}\texttt{new int[10]} \Rightarrow 40\text{字节)} \end{cases} $$ `delete`仅释放右侧的堆空间,左侧指针变量在作用域结束时自动回收[^2][^5]。 > **最佳实践**:优先使用智能指针(C++11+),其次在`delete`后必须置空指针。对于数组,严格匹配`new[]`与`delete[]`[^1][^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值