C++ 智能指针

本文主要介绍 C++11 引入的三个智能指针: std::unique_ptr<T>std::shared_ptr<T>std::weak_ptr<T>

不要忘记添加头文件 memory

std::unique_ptr<T>

这个指针会在离开指针作用域时自动释放资源。

例子:

1
2
3
4
5
6
7
8
9
{
std::unique_ptr<int> p = std::make_unique<int>(10);
//...
}
//也可以写成
{
std::unique_ptr<int> p(new int(10));
//...
}

等价于

1
2
3
4
5
{
int *p = new int(10);
//...
delete p;
}

注意:同一时刻只能有一个unique_ptr指针指向给定资源,即这个指针是move-only的,这主要是为了防止一个资源被释放后,再通过另外一个指针访问。
例如:

1
2
3
4
5
6
7
8
9
{
std::unique_ptr<int> p = std::make_unique<int>(10);

//这样是不被允许的
std::unique_ptr<int> p1 = p2;

//但这样是可以的,而且经过这一步操作后,p就成了空指针
std::unique_ptr<int> p = std::move(p);
}

std::shared_ptr<T>

这个指针是对指向的资源引用进行计数,当引用计数为0时,则释放资源。正因如此,这个指针的性能开销要略大于 裸指针 和 unique_ptr
例子:

1
2
3
4
5
6
7
8
9
{
std::shared_ptr<int> p = std::make_shared<int>(10);
//...
}
//也可以写成
{
std::shared_ptr<int> p(new int(10));
//...
}

我们可以通过方法use_count()查看引用计数:

1
2
3
4
5
6
7
8
9
10
{
std::shared_ptr<int> p = std::make_shared<int>(10);
std::cout << p.use_count(); //输出1
{
std::shared_ptr<int> p1 = p;
std::cout << p.use_count(); //输出2
}
std::cout << p.use_count(); //输出1
}
//此时引用计数为0,资源被释放

std::weak_ptr<T>

这个指针是为了配合std::shared_ptr而引入的一种智能指针,不具有普通指针的行为。std::weak_ptr可以指向std::shared_ptr指向的资源而不改变引用计数。当指向的std::shared_ptr所指向的资源被释放时,std:::weak_ptr指针会自动变成空指针。
当要使用std::weak_ptr指针时,则需要将其提升为std::shared_ptr指针。

例子:

1
2
3
4
5
6
7
8
9
10
{
std::shared_ptr<int> p(new int(10));
std::weak_ptr<int> p1 = p;
std::cout << p.use_count(); //输出1

//判断p1指向的p是否释放,如果释放 p1.lock() 会返回空指针
if(p1.expired()){
std::shared_ptr<int> p2 = p1.lock();
std::cout << p.use_count(); //输出2
}

小结

  • std::unique_ptr<T>:用于资源被独占的情况下
  • std::shared_ptr<T>:用于资源被共享的情况下
  • std::weak_ptr<T>:解决循环引用等问题

参考资料:

https://zhuanlan.zhihu.com/p/150555165
https://www.cnblogs.com/wxquare/p/4759020.html