📌 为什么智能指针避免传入裸指针?
在 C++11 及之后的标准中,智能指针(std::unique_ptr、std::shared_ptr)被引入 替代裸指针(raw pointer,T*),提供自动化内存管理,避免手动 delete 带来的内存泄漏和悬挂指针(dangling pointer)。
然而,在使用智能指针时,不推荐直接传入裸指针(T*),尤其是在 std::shared_ptr 中,主要是因为可能导致“重复释放(double delete)”问题。
📌 1. 为什么 std::shared_ptr<T> 不能直接传入裸指针?
🚨 直接使用 new 创建的裸指针传入 std::shared_ptr<T> 可能会导致 double delete,引发未定义行为(UB,Undefined Behavior)。
✅ 1️⃣ 正确使用 std::make_shared()
#include <iostream>
#include <memory>
struct MyClass {
MyClass() { std::cout << "Constructor\n"; }
~MyClass() { std::cout << "Destructor\n"; }
};
int main() {
std::shared_ptr<MyClass> sp1 = std::make_shared<MyClass>(); // ✅ 正确
std::shared_ptr<MyClass> sp2 = sp1; // ✅ 共享所有权,正确
}
✅ std::make_shared<T>() 更安全,避免 double delete 问题。
❌ 2️⃣ 直接传入 new 的裸指针,可能导致 double delete
#include <iostream>
#include <memory>
struct MyClass {
MyClass() { std::cout << "Constructor\n"; }
~MyClass() { std::cout << "Destructor\n"; }
};
int main() {
MyClass* raw = new MyClass();
std::shared_ptr<MyClass> sp1(raw); // 🚨 `sp1` 负责释放 `raw`
std::shared_ptr<MyClass> sp2(raw); // 🚨 `sp2` 也负责释放 `raw`,double delete!
}
🚨 问题:
sp1拿到raw的所有权,并在sp1的use_count == 0时释放raw。sp2重复持有raw,导致sp2也在析构时释放raw。- 最终
raw被delete两次,产生未定义行为!
📌 2. 为什么 std::make_shared<T>() 更安全?
std::make_shared<T>() 分配单个内存块,减少分配开销,并避免 double delete。
✅ 内存布局
❌ 直接 new 的情况
[std::shared_ptr] -> [control block]
[std::shared_ptr] -> [control block]
[raw pointer] -> [对象数据]
📌 不同的 shared_ptr 实例可能管理相同 raw pointer,导致 double delete。
✅ std::make_shared<T>() 的情况
[std::shared_ptr] -> [control block + 对象数据]
[std::shared_ptr] -> [control block + 对象数据]
📌 对象和控制块在同一块内存中,引用计数清零时自动释放。
📌 3. 为什么 std::unique_ptr<T> 不能传入已存在的裸指针?
std::unique_ptr<T> 是独占所有权(Ownership),它不能共享一个 T*。
✅ 正确的 std::unique_ptr<T>
#include <iostream>
#include <memory>
struct MyClass {
MyClass() { std::cout << "Constructor\n"; }
~MyClass() { std::cout << "Destructor\n"; }
};
int main() {
std::unique_ptr<MyClass> up1 = std::make_unique<MyClass>(); // ✅ 推荐
std::unique_ptr<MyClass> up2 = std::move(up1); // ✅ 通过 `move` 转移所有权
}
❌ 传入已存在的 new 指针
MyClass* raw = new MyClass();
std::unique_ptr<MyClass> up1(raw);
std::unique_ptr<MyClass> up2(raw); // 🚨 两个 `unique_ptr` 管理相同 `raw`,double delete!
🚨 up1 和 up2 都会在析构时 delete raw,导致 double delete。
📌 4. 什么时候应该传裸指针?
📌 可以安全地传递 T* 给 std::shared_ptr<T>,但前提是指针不再被 delete。
void foo(std::shared_ptr<MyClass> sp) { }
int main() {
std::shared_ptr<MyClass> sp = std::make_shared<MyClass>();
foo(sp); // ✅ 传递 `shared_ptr`,不会导致 double delete
}
🚨 不要手动 new 一个裸指针然后传递给多个 shared_ptr!
📌 5. 总结
✅ 智能指针管理对象生命周期,裸指针不能重复管理相同对象。
✅ 不要直接传递 new 出来的裸指针给多个 shared_ptr,使用 std::make_shared<T>() 代替。
✅ std::unique_ptr<T> 不能共享所有权,传递时必须 std::move()。
✅ 如果必须传裸指针,确保 new 出来的对象不会被多个 shared_ptr 直接管理。
🚀 如果你在 C++ 编程中想避免内存泄漏和 double delete,使用 std::make_shared<T>() 是最好的选择!🔥
645

被折叠的 条评论
为什么被折叠?



