You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中多指针指向同一内存时,如何避免delete后的未定义行为?

规避C++中多指针指向同一块内存的未定义行为

你的示例代码里,ptr和anotherPtr指向同一块堆内存,执行delete ptr后,这块内存会被归还给操作系统,但anotherPtr依然保留着原来的内存地址——此时它变成了野指针,再通过它调用成员函数属于未定义行为:可能侥幸输出旧值,也可能直接导致程序崩溃,行为完全不可预测。

下面是几种实用的规避方法:

  • 手动置空所有关联指针:执行delete后,立刻将所有指向该内存的指针设为nullptr,后续使用前先检查指针是否为空。修改你的示例代码:

    delete ptr;
    ptr = nullptr;
    anotherPtr = nullptr; // 同步置空所有指向该内存的指针
    // 后续使用前判断:if (anotherPtr != nullptr) { ... }
    

    这种方法依赖手动维护,适合简单场景,但容易因遗漏置空导致问题。

  • 使用智能指针(推荐方案):C++11及以后的标准库提供了std::shared_ptr和std::unique_ptr,能自动管理内存生命周期,彻底避免野指针。

    • std::shared_ptr通过引用计数跟踪内存:每当有新的shared_ptr指向该内存,计数加1;当shared_ptr被销毁或重置,计数减1。当计数降到0时,自动释放内存。
      改写你的示例:
      #include <iostream>
      #include <memory>
      using namespace std;
      
      class MyClass {
      private:
          int data;
      public:
          MyClass(int d) : data(d) {}
          int getData() const { return data; }
      };
      
      int main() {
          shared_ptr<MyClass> ptr = make_shared<MyClass>(5);
          cout << "Data using pointer: " << ptr->getData() << endl;   
      
          shared_ptr<MyClass> anotherPtr = ptr; // 引用计数变为2
      
          // 无需手动delete,当ptr和anotherPtr都离开作用域时,内存自动释放
          cout << "Data using another pointer: " << anotherPtr->getData() << endl;
      
          ptr.reset(); // 引用计数减为1,此时anotherPtr仍指向有效内存
          cout << "Data after reset ptr: " << anotherPtr->getData() << endl;
      
          return 0;
      }
      
    • 如果内存只能由一个指针独占所有权,用std::unique_ptr:它不允许拷贝,只能通过移动语义转移所有权,从根源上避免多指针共享同一块内存的情况:
      unique_ptr<MyClass> ptr = make_unique<MyClass>(5);
      unique_ptr<MyClass> anotherPtr = move(ptr); // ptr变为空,所有权转移给anotherPtr
      // 只有anotherPtr拥有内存,释放时机由它决定
      
  • 项目层面禁用裸指针手动管理:在团队项目中约定,仅用智能指针管理堆内存,禁止直接调用new和delete,从源头杜绝野指针问题。

内容的提问来源于stack exchange,提问作者Muhammad Ahsan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:56:19