C++11引入了智能指针(Smart Pointers)的概念,它们是一种自动管理内存的生命周期的指针类型,帮助开发者避免内存泄漏和野指针等问题。C++11标准库中定义了三种智能指针:std::unique_ptr、std::shared_ptr和std::weak_ptr。
原理
- std::unique_ptr:独占所有权模型,同一时间只能有一个unique_ptr指向某个对象,当unique_ptr被销毁(例如离开作用域)时,它所指向的对象也会被自动删除。
- std::shared_ptr:共享所有权模型,多个shared_ptr可以指向同一个对象,对象的生命周期会持续到最后一个拥有它的shared_ptr被销毁。当最后一个shared_ptr被销毁时,对象会被自动删除。shared_ptr使用引用计数(reference counting)来实现。
- std::weak_ptr:弱引用模型,weak_ptr是对对象的一种弱引用,它不会增加对象的引用计数。它主要用于解决shared_ptr之间的循环引用问题。
使用案例
std::unique_ptr
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "MyClass created\n"; }
~MyClass() { std::cout << "MyClass destroyed\n"; }
};
int main() {
std::unique_ptr<MyClass> ptr(new MyClass()); // 分配并初始化
// 当ptr离开作用域时,MyClass对象会被自动删除
return 0;
}
std::shared_ptr
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass created\n"; }
~MyClass() { std::cout << "MyClass destroyed\n"; }
};
int main() {
std::shared_ptr<MyClass> ptr1(new MyClass()); // 分配并初始化
std::shared_ptr<MyClass> ptr2 = ptr1; // ptr2和ptr1共享同一个对象
// 当ptr1和ptr2都离开作用域时,MyClass对象才会被删除
return 0;
}
std::weak_ptr 解决循环引用
#include <memory>
#include <iostream>
class A;
class B;
class A {
public:
std::shared_ptr<B> b_ptr;
~A() { std::cout << "A destroyed\n"; }
};
class B {
public:
std::weak_ptr<A> a_wptr;
~B() { std::cout << "B destroyed\n"; }
};
int main() {
std::shared_ptr<A> a_ptr(new A());
std::shared_ptr<B> b_ptr(new B());
a_ptr->b_ptr = b_ptr;
b_ptr->a_wptr = a_ptr;
// 由于使用了weak_ptr,A和B对象都可以被正确删除
return 0;
}
注意:在实际使用中,尽量避免裸指针(raw pointers)和new/delete的直接使用,而是尽可能地使用智能指针来管理内存。
总结:
- 熟悉C++11引入的三种智能指针的原理及判断使用场景;
- 理解unique_ptr对auto_ptr的替换;
- 三种指针都是将一些释放操作自动化实现,也可以自己手写智能指针;
- 一张表格分辨四种智能指针:
auto_ptr (已废弃) | unique_ptr | shared_ptr | weak_ptr | |
---|---|---|---|---|
所有权 | 独有(但有问题的拷贝语义) | 独有 | 共享(引用计数) | 不拥有(观察) |
拷贝语义 | 转移所有权(可能导致问题) | 禁止拷贝,但可以移动 | 引用计数增加 | 不支持 |
赋值语义 | 转移所有权(可能导致问题) | 禁止赋值,但可以移动赋值 | 引用计数增加 | 不支持 |
销毁 | 当auto_ptr对象销毁时,原对象也被销毁 | 当unique_ptr对象销毁时,原对象也被销毁 | 当最后一个shared_ptr对象销毁时,原对象被销毁 | 不负责销毁原对象 |
循环引用 | 不适用 | 不适用 | 可能导致问题(需要weak_ptr解决) | 用于解决shared_ptr的循环引用问题 |
安全性 | 低(已废弃) | 高 | 高(但需注意循环引用) | 高(作为shared_ptr的补充) |