在 C++ 传统的内存管理方式中,动态分配的对象需要手动释放,否则可能会导致 内存泄漏(Memory Leak)。为了解决这个问题,C++11 引入了 智能指针(Smart Pointer),它能 自动管理资源,避免内存泄漏。
本篇博客将介绍:
unique_ptr
、shared_ptr
、weak_ptr
智能指针是一个 包装类,用于管理动态分配的对象,并在 不再需要对象时自动释放内存。
C++ 提供了三种智能指针:
智能指针 | 特点 | 适用场景 |
---|---|---|
unique_ptr |
独占所有权,不能共享 | 适用于 唯一所有权 |
shared_ptr |
共享所有权,使用 引用计数 | 适用于 多个对象共享同一资源 |
weak_ptr |
弱引用,不影响引用计数 | 适用于 避免循环引用 |
unique_ptr
(独占所有权)unique_ptr
的基本用法#include
#include
class Foo {
public:
Foo() { std::cout << "Foo 构造\n"; }
~Foo() { std::cout << "Foo 析构\n"; }
void show() { std::cout << "Hello from Foo\n"; }
};
int main() {
std::unique_ptr<Foo> ptr = std::make_unique<Foo>(); // 创建 unique_ptr
ptr->show(); // 访问对象成员
return 0; // 离开作用域时,Foo 自动销毁
}
解析
std::unique_ptr ptr = std::make_unique();
✅ 推荐使用 make_unique
unique_ptr
不能被复制,只能 移动。unique_ptr
不能复制std::unique_ptr<Foo> ptr1 = std::make_unique<Foo>();
std::unique_ptr<Foo> ptr2 = ptr1; // ❌ 错误:不能复制
unique_ptr
的所有权转移std::unique_ptr<Foo> ptr1 = std::make_unique<Foo>();
std::unique_ptr<Foo> ptr2 = std::move(ptr1); // ✅ 允许移动
shared_ptr
(共享所有权)shared_ptr
的基本用法#include
#include
class Foo {
public:
Foo() { std::cout << "Foo 构造\n"; }
~Foo() { std::cout << "Foo 析构\n"; }
};
int main() {
std::shared_ptr<Foo> ptr1 = std::make_shared<Foo>();
std::shared_ptr<Foo> ptr2 = ptr1; // 共享同一对象
std::cout << "引用计数: " << ptr1.use_count() << std::endl; // 2
return 0; // 当最后一个 shared_ptr 离开作用域时,Foo 被销毁
}
解析
std::make_shared()
✅ 推荐使用 make_shared
shared_ptr
可以被多个指针共享。use_count()
查看当前引用计数。shared_ptr
的引用计数std::shared_ptr<int> sp1 = std::make_shared<int>(100);
std::shared_ptr<int> sp2 = sp1; // sp1 和 sp2 共享对象
std::cout << sp1.use_count() << std::endl; // 输出 2
weak_ptr
(弱引用)weak_ptr
的基本用法#include
#include
class Foo {
public:
Foo() { std::cout << "Foo 构造\n"; }
~Foo() { std::cout << "Foo 析构\n"; }
};
int main() {
std::shared_ptr<Foo> sp = std::make_shared<Foo>();
std::weak_ptr<Foo> wp = sp; // 创建 weak_ptr
std::cout << "引用计数: " << sp.use_count() << std::endl; // 1
if (auto locked = wp.lock()) { // 转换为 shared_ptr
std::cout << "对象仍然存在\n";
}
return 0;
}
解析
weak_ptr
不会影响引用计数lock()
转换为 shared_ptr
才能访问对象shared_ptr
循环引用。shared_ptr
循环引用#include
#include
class B;
class A {
public:
std::shared_ptr<B> bptr;
~A() { std::cout << "A 析构\n"; }
};
class B {
public:
std::weak_ptr<A> aptr; // 解决循环引用
~B() { std::cout << "B 析构\n"; }
};
int main() {
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<B> b = std::make_shared<B>();
a->bptr = b;
b->aptr = a; // 解决循环引用
return 0;
}
解析
weak_ptr
不会增加引用计数,避免了 shared_ptr
循环引用导致的内存泄漏。智能指针 | 所有权 | 引用计数 | 是否可以共享 | 适用场景 |
---|---|---|---|---|
unique_ptr |
独占 | 无 | ❌ | 单个对象,唯一所有权 |
shared_ptr |
共享 | 有 | ✅ | 多个对象共享同一资源 |
weak_ptr |
弱引用 | 无 | ✅(但不影响计数) | 避免 shared_ptr 循环引用 |
✅ unique_ptr
适用于 独占资源,不可复制,但可移动
✅ shared_ptr
适用于 共享资源,引用计数自动管理
✅ weak_ptr
适用于 避免 shared_ptr
循环引用
下一篇 C++学习系列(12):C++ 线程与多线程编程,敬请期待!
如果你喜欢这篇文章,欢迎点赞、收藏,并关注本系列!