三种智能指针的使用场景shared_ptr、unique_ptr和weak_ptr
三种智能指针的使用场景shared_ptr、unique_ptr和weak_ptr
C++11引入了三种智能指针:shared_ptr,unique_ptr和weak_ptr,它们用于解决原生指针可能导致的内存泄露和非法引用问题。下面我们分别看一下这三种智能指针的使用场景:
- shared_ptr:shared_ptr是一种引用计数的智能指针,当你需要在多个地方共享同一个资源时,可以使用它。它会跟踪引用到某个对象的shared_ptr数量。当最后一个shared_ptr离开其作用范围或者被赋予新的值时,它所指向的对象就会被自动删除。在循环引用的情况下,需要配合使用weak_ptr避免内存泄露。
- unique_ptr:unique_ptr是一种具有严格所有权语义的智能指针,它不允许多个指针指向同一对象。因此,unique_ptr适合在作用域内拥有对象的独占所有权,并且在作用域结束时需要自动释放该对象。例如,它可以用于防止资源泄漏(如打开的文件或分配的内存)。
- weak_ptr:weak_ptr是为了配合shared_ptr而存在的,它可以从一个shared_ptr或者另一个weak_ptr对象构造,其目的是提供对管理对象的访问,但是它并不改变引用计数。你可以把weak_ptr看作是shared_ptr的一个安全版本,用于解决shared_ptr可能存在的循环引用问题。当其所指向的对象被释放后,尝试通过weak_ptr访问对象将抛出一个std::bad_weak_ptr异常。
在使用智能指针时,应尽量优先选择unique_ptr,如果你确实需要多个所有者,那么应选择shared_ptr。在处理shared_ptr可能产生的循环引用问题时,应使用weak_ptr。
在深入探讨这些智能指针的使用场景之前,我们需要理解它们的设计原则以及如何正确地使用它们。
unique_ptr
unique_ptr的主要用途是管理一个对象的生命周期。当unique_ptr被销毁时,它会自动销毁(或释放)其所有权的对象。这可以确保在任何情况下,包括异常,都可以正确释放资源。
例如,你可能会在一个函数中创建一个动态数组,并希望这个数组在函数返回或出现异常时被正确地删除。在这种情况下,你可以使用unique_ptr来管理这个数组。
unique_ptr示例
1 |
|
shared_ptr
shared_ptr的主要用途是在多个对象之间共享所有权。shared_ptr使用引用计数来跟踪有多少个shared_ptr对象共享同一个资源。当最后一个shared_ptr被销毁时,其管理的资源也会被自动释放。
例如,如果你有一个需要在多个线程之间共享的大对象,并且你希望当最后一个需要它的线程完成时删除这个对象,你就可以使用shared_ptr。
shared_ptr示例
1 |
|
- 如何理解shared_ptr是在多个对象之间共享所有权
shared_ptr是一种智能指针,它允许多个指针引用同一个对象。这是通过引用计数实现的,即每个shared_ptr都会跟踪有多少个shared_ptr实例引用同一个对象。当一个shared_ptr实例被销毁或者重新指向其他对象时,原来对象的引用计数减1,当引用计数减为0时,对象将被自动删除。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <iostream>
#include <memory>
int main()
{
std::shared_ptr<int> sp1(new int(10));
std::cout << "sp1's value: " << *sp1 << std::endl;
std::cout << "Use count: " << sp1.use_count() << std::endl;
std::shared_ptr<int> sp2 = sp1; // 复制shared_ptr,sp1和sp2现在指向同一个对象,引用计数增加
std::cout << "sp2's value: " << *sp2 << std::endl;
std::cout << "Use count: " << sp2.use_count() << std::endl; // use_count现在应为2,因为有两个shared_ptr指向同一个对象
sp1.reset(); // sp1不再指向对象,引用计数减1
std::cout << "After resetting sp1, use count: " << sp2.use_count() << std::endl; // use_count现在应为1
return 0;
}
在这个示例中,我们创建了两个shared_ptr,sp1和sp2,它们共享同一个动态分配的int对象。通过调用use_count()函数,我们可以看到每个shared_ptr实例销毁或者重新指向其他对象时引用计数的变化。
weak_ptr
weak_ptr的主要用途是避免shared_ptr可能产生的循环引用问题。循环引用问题是指两个或更多的shared_ptr对象互相引用,形成一个循环。这会导致对象无法被正确释放。
例如,如果你有一个类A和一个类B,并且A有一个指向B的shared_ptr,B也有一个指向A的shared_ptr,这就会产生一个循环引用。解决这个问题的方法就是将其中一个shared_ptr改为weak_ptr。这样,当一方不再需要时,可以被正确地释放。
weak_ptr示例
1 |
|