文章目录
C++智能指针是一种自动管理动态内存的工具,通过RAII(资源获取即初始化)机制防止内存泄漏。以下是主要类型及示例:
一、智能指针的作用
- 自动释放内存:避免因忘记
delete
导致内存泄漏。 - 所有权管理:明确资源的所有权归属(独占或共享)。
- 异常安全:在代码异常时仍能正确释放内存。
二、unique_ptr
:独占所有权
- 特点:同一时间只能有一个
unique_ptr
拥有对象,不可复制,但可通过std::move
转移所有权。 - 适用场景:明确资源唯一所有者的场景(如工厂模式返回对象)。
示例代码
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass 构造\n"; }
~MyClass() { std::cout << "MyClass 析构\n"; }
void print() { std::cout << "Hello from MyClass\n"; }
};
int main() {
std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(); // 创建
ptr1->print();
// 转移所有权给 ptr2
std::unique_ptr<MyClass> ptr2 = std::move(ptr1);
if (!ptr1) {
std::cout << "ptr1 已释放所有权\n";
}
ptr2->print();
return 0;
}
输出结果:
MyClass 构造
Hello from MyClass
ptr1 已释放所有权
Hello from MyClass
MyClass 析构
三、shared_ptr
:共享所有权
- 特点:通过引用计数管理资源,多个指针共享同一对象,计数为0时释放内存。
- 适用场景:需要多个对象共享同一资源的场景(如多线程缓存)。
示例代码
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass 构造\n"; }
~MyClass() { std::cout << "MyClass 析构\n"; }
};
int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
{
std::shared_ptr<MyClass> ptr2 = ptr1; // 引用计数+1(总计数=2)
std::cout << "内部作用域,计数: " << ptr1.use_count() << "\n";
} // ptr2 析构,计数-1(总计数=1)
std::cout << "外部作用域,计数: " << ptr1.use_count() << "\n";
return 0;
}
输出结果:
MyClass 构造
内部作用域,计数: 2
外部作用域,计数: 1
MyClass 析构
四、weak_ptr
:解决循环引用
- 特点:观察但不拥有资源,不增加引用计数,需通过
lock()
转为shared_ptr
使用。 - 适用场景:打破
shared_ptr
循环引用(如双向链表、观察者模式)。
循环引用示例与解决
#include <memory>
#include <iostream>
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
~A() { std::cout << "A 析构\n"; }
};
class B {
public:
// std::shared_ptr<A> a_ptr; // 导致循环引用
std::weak_ptr<A> a_ptr; // 使用 weak_ptr 解决
~B() { std::cout << "B 析构\n"; }
};
int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b_ptr = b;
b->a_ptr = a; // weak_ptr 不增加引用计数
return 0;
}
输出结果:
A 析构
B 析构
五、注意事项
- 弃用
auto_ptr
:C++11起废弃,用unique_ptr
替代。 - 优先使用
make_shared
/make_unique
:更高效且避免内存泄漏(C++14支持make_unique
)。 - 避免裸指针与智能指针混用:可能引发重复释放。
- 循环引用:必须用
weak_ptr
打破。
六、总结
unique_ptr
:独占资源,性能最优。shared_ptr
:共享资源,注意循环引用。weak_ptr
:配合shared_ptr
解决循环问题。
智能指针能显著提升代码安全性和可维护性,是现代C++内存管理的核心工具。