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
相关产品推荐
相关产品推荐

