shared_ptr 智能指针
文章目录
为什么要引入智能指针
在C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。
智能指针的作用
- 自动管理动态内存:智能指针通过 RAII(资源获取即初始化)机制自动释放内存。RAII 是 C++ 的核心设计理念之一,资源的生命周期与对象的生命周期绑定,从而确保资源不会被泄漏。
- 避免内存泄漏:智能指针通过引用计数或其他机制,确保内存能够在不再使用时自动释放。
- 避免悬挂指针和野指针:智能指针能够在其不再使用时自动销毁,避免了手动删除后指针仍然存在的危险。
- 确保异常安全:智能指针通过作用域控制内存,确保即使发生异常,也能正确释放资源。
- 简化代码:相比传统指针手动管理内存,智能指针大大简化了内存管理代码,提升了程序的可维护性和可靠性。
C++ 中的智能指针种类
std::unique_ptr
- 用途:表示独占所有权的智能指针,意味着一个
unique_ptr
只能拥有一个对象的所有权。不能被复制,只能移动。 - 特点
- 独占所有权:同一个对象只能有一个
unique_ptr
管理,避免了多重释放的问题。 - 不可拷贝:不能通过拷贝构造函数或赋值操作符来复制,确保了对象的唯一所有权。
- 可以转移所有权:可以通过
std::move
将unique_ptr
的所有权从一个指针转移到另一个。
- 独占所有权:同一个对象只能有一个
- 典型用法
std::unique_ptr<int> ptr1 = std::make_unique<int>(10);
std::unique_ptr<int> ptr2 = std::move(ptr1); // 转移所有权
std::shared_ptr
- 用途:表示共享所有权的智能指针,多个
shared_ptr
可以共同拥有同一个对象的所有权。 - 特点
- 引用计数:
shared_ptr
使用引用计数的机制来跟踪有多少个shared_ptr
指向同一对象。当最后一个指向对象的shared_ptr
被销毁时,内存会自动释放。 - 可以拷贝和赋值:
shared_ptr
可以通过拷贝构造和赋值操作符进行拷贝,因此它适用于多个地方共享资源的情况。 - 线程安全:
shared_ptr
在修改引用计数时是线程安全的,但对象本身的操作仍需要额外的同步机制。
- 引用计数:
- 典型用法
std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
std::shared_ptr<int> ptr2 = ptr1; // 引用计数增加,两个指针共享所有权
std::weak_ptr
- 用途:用于解决
shared_ptr
引用计数环的问题。weak_ptr
并不增加引用计数,只是观察shared_ptr
指向的对象。 - 特点
- 不增加引用计数:
weak_ptr
不会增加shared_ptr
的引用计数,因此不会影响对象的生命周期。 - **可以转换为 **
shared_ptr
:如果对象仍然存在,weak_ptr
可以通过lock()
方法转换为shared_ptr
,从而访问对象。 - 防止循环引用:在
shared_ptr
之间形成循环引用时,weak_ptr
可以用来打破这种循环,避免内存泄漏。
- 不增加引用计数:
- 典型用法
std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
std::weak_ptr<int> weakPtr = ptr1; // 不增加引用计数
if (auto ptr2 = weakPtr.lock()) {
// 如果对象还存在,获得一个 shared_ptr
// 使用 ptr2
}
std::shared_ptr
使用 std::make_shared
创建 shared_ptr
(推荐方式)
std::make_shared 是创建 std::shared_ptr 的推荐方法,它同时分配 shared_ptr 和对象的内存,能够提高效率并减少内存分配次数。
使用std::make_shared()模板函数可以完成内存地址的创建,并将最终得到的内存地址传递给共享智能指针对象管理。如果申请的内存是普通类型,通过函数的()可完成地址的初始化,如果要创建一个类对象,函数的()内部需要指定构造对象需要的参数,也就是类构造函数的参数。
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructor\n"; }
~MyClass() {
std::cout << "MyClass destructor\n"; }
void say_hello() {
std::cout << "Hello, World!\n"; }
};
int main() {
// 使用 std::make_shared 创建 shared_ptr