这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战
聊聊智能指针
Effective Modern C++中这样评价指针:
- 裸指针声明并不确定其指向的是单个对象还是数组。
- 裸指针不声明其指向对象是否需要及何时析构
- 没有方法能够检测出一个指针是否空悬,即某个对象已经析构了,有指针依然指向它,产生空指针。
因而引入了智能指针:std::auto_ptr,std::unique_ptr,std::shared_ptr,std::weak_ptr
。这四种智能指针中,std::auto_ptr可以看作废弃的特性,只有在C++98编译器下才会使用它。聊聊其他三种智能指针。
std::unique_ptr
std::unique_ptr是最常用的智能指针,使用普通指针时,要删除:
{
int* p = new int(100);
// ...
delete p; // 要记得释放内存
}
使用智能指针时:
std::unique_ptr<int> uptr = std::make_unique<int>(200);
\\ 指向数组的形式
{
std::unique_ptr<int[]> uptr = std::make_unique<int[]>(10);
for (int i = 0; i < 10; i++) {
uptr[i] = i * i;
}
for (int i = 0; i < 10; i++) {
std::cout << uptr[i] << std::endl;
}
}
std::unique_ptr的默认析构方法是Delete,也可以用如下方法自定义析构:
{
struct FileCloser {
void operator()(FILE* fp) const {
if (fp != nullptr) {
fclose(fp);
}
}
};
std::unique_ptr<FILE, FileCloser> uptr(fopen("test_file.txt", "w"));
}
std::shared_ptr
std::shared_ptr对资源进行计数,为0时释放资源,其初始化与复制赋值如下:
std::shared_ptr<int> sptr = std::make_shared<int>(200);
std::shared_ptr<int> sptr1 = sptr;
assert(sptr.use_count() == 2); // sptr 和 sptr1 共享资源,引用计数为 2
std::weak_ptr
来个例子:
void Observe(std::weak_ptr<int> wptr) {
if (auto sptr = wptr.lock()) {
std::cout << "value: " << *sptr << std::endl;
} else {
std::cout << "wptr lock fail" << std::endl;
}
}
std::weak_ptr<int> wptr;
{
auto sptr = std::make_shared<int>(111);
wptr = sptr;
Observe(wptr); // sptr 指向的资源没被释放,wptr 可以成功提升为 shared_ptr
}
Observe(wptr); // sptr 指向的资源已被释放,wptr 无法提升为 shared_ptr
可以看到std::weak_ptr与std::shared_ptr一起使用,std::weak_ptr不参与std::shared_ptr的计数操作,但能检测出其是否空悬,上面这个例子当shared_ptr 管理的资源被释放时,weak_ptr 会自动变成 nullptr