shared_ptr 智能指针

shared_ptr 智能指针

为什么要引入智能指针

在C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。

智能指针的作用

  1. 自动管理动态内存:智能指针通过 RAII(资源获取即初始化)机制自动释放内存。RAII 是 C++ 的核心设计理念之一,资源的生命周期与对象的生命周期绑定,从而确保资源不会被泄漏。
  2. 避免内存泄漏:智能指针通过引用计数或其他机制,确保内存能够在不再使用时自动释放。
  3. 避免悬挂指针和野指针:智能指针能够在其不再使用时自动销毁,避免了手动删除后指针仍然存在的危险。
  4. 确保异常安全:智能指针通过作用域控制内存,确保即使发生异常,也能正确释放资源。
  5. 简化代码:相比传统指针手动管理内存,智能指针大大简化了内存管理代码,提升了程序的可维护性和可靠性。

C++ 中的智能指针种类

  1. std::unique_ptr
  • 用途:表示独占所有权的智能指针,意味着一个 unique_ptr 只能拥有一个对象的所有权。不能被复制,只能移动。
  • 特点
    • 独占所有权:同一个对象只能有一个 unique_ptr 管理,避免了多重释放的问题。
    • 不可拷贝:不能通过拷贝构造函数或赋值操作符来复制,确保了对象的唯一所有权。
    • 可以转移所有权:可以通过 std::moveunique_ptr 的所有权从一个指针转移到另一个。
  • 典型用法
std::unique_ptr<int> ptr1 = std::make_unique<int>(10);
std::unique_ptr<int> ptr2 = std::move(ptr1);  // 转移所有权
  1. 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;  // 引用计数增加,两个指针共享所有权
  1. 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liknana

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值