C++特性之智能指针shared_ptr详解

C++特性之智能指针shared_ptr详解

什么是智能指针?

智能指针是C ++中的一个重要特性,它可以避免内存泄漏和悬空指针的问题。智能指针是一个C ++类,它的析构函数自动释放分配的内存。最常见的智能指针有:

  • unique_ptr
  • shared_ptr
  • weak_ptr

其中shared_ptr是引用计数智能指针。这种智能指针在控制对象之间的共享所有权方面非常有用。它使用引用计数来跟踪有多少个指针指向同一个对象,并在不需要它时自动删除对象。

shared_ptr的使用方法

shared_ptr是一个模板类,它和unique_ptr一样,通常使用std命名空间。我们来看一下shared_ptr的使用方法。

向shared_ptr分配内存的方式有两种,一种是通过new运算符直接进行内存分配,另一种是通过std::make_shared函数进行分配。

通过new运算符分配内存的方式

std::shared_ptr<int> p1(new int(10));
std::shared_ptr<std::string> p2(new std::string("hello shared_ptr"));

在上述例子中,我们使用了new运算符来分配内存,并将其传递给shared_ptr构造函数。通过new运算符分配内存的方式需要显式释放内存,不然会导致内存泄漏。当使用shared_ptr管理指针时,不需要显示调用delete函数释放内存。

通过std::make_shared函数分配内存的方式

auto p3 = std::make_shared<int>(10);
auto p4 = std::make_shared<std::string>("hello shared_ptr");

使用std::make_shared函数可以更加方便的分配内存,这种方式不需要显式的释放内存,因为智能指针会自动进行管理,并在对象不再被使用时释放对象所占用的内存。

shared_ptr的拷贝和移动

shared_ptr是一个指向对象的指针,多个shared_ptr可以指向同一个对象。每个shared_ptr都有一个引用计数器,当有一个新的shared_ptr指向该对象时,计数器值加一。当任意一个shared_ptr生命周期结束时,计数器值减一。只有当计数器值为零时,才会释放对象的内存。

下面我们看一个简单的例子.

#include <iostream>
#include <memory>

int main() {
    auto p1 = std::make_shared<int>(10);
    std::cout << "p1 count:" << p1.use_count() << std::endl;
    {
        auto p2 = p1;
        std::cout << "p1 count:" << p1.use_count() << std::endl;
        std::cout << "p2 count:" << p2.use_count() << std::endl;
    }
    std::cout << "p1 count:" << p1.use_count() << std::endl;
    return 0;
}

输出结果如下所示:

p1 count:1
p1 count:2
p2 count:2
p1 count:1

该程序分别创建了两个shared_ptr,p1和p2,它们都指向同一个整型对象。在创建p2时,p2指向p1所指向的对象,并且两者拥有相同的计数器。当内部作用域结束时,p2被销毁并计数器减一,但p1仍然存在,因此p1的计数器不为零。在程序结束时,p1销毁并计数器减一,因此计数器为零,整型对象被销毁。

shared_ptr可以通过拷贝和移动进行赋值,下面我们来看一下拷贝和移动的用法。

#include <iostream>
#include <memory>

int main() {
    auto p1 = std::make_shared<int>(10);
    std::cout << "p1 count:" << p1.use_count() << std::endl;
    auto p2(p1);
    std::cout << "p1 count:" << p1.use_count() << std::endl;
    std::cout << "p2 count:" << p2.use_count() << std::endl;
    auto p3 = std::move(p1);
    std::cout << "p1 count:" << p1.use_count() << std::endl;
    std::cout << "p3 count:" << p3.use_count() << std::endl;
    return 0;
}

输出结果如下所示:

p1 count:1
p1 count:2
p2 count:2
p1 count:0
p3 count:2

在上面的例子中,首先创建共享指针p1并将其数量计为1。然后通过拷贝构造函数创建了两个新的共享指针p2和p1,并将其数值增加至2。接下来,使用std::move操作将p1的所有权转移给p3,并使p1指向null。此时,p3和p2计数器的值都为2,而p1指向null。

shared_ptr的示例说明

下面是一个使用shared_ptr管理动态数组的示例:

#include <iostream>
#include <memory>

int main() {
    auto p1 = std::make_shared<int[]>(3);
    p1[0] = 10;
    p1[1] = 20;
    p1[2] = 30;
    for (int i = 0; i < 3; i++) {
        std::cout << "p1[" << i << "]=" << p1[i] << std::endl;
    }
    return 0;
}

上面的代码创建了一个动态数组,并使用shared_ptr管理动态数组的内存。我们可以像使用原生数组一样来操作p1,包括访问元素和遍历。当程序结束时,p1所占用的内存会自动释放。

下面是一个示例,使用shared_ptr构建一个类的实例。

#include <iostream>
#include <memory>

class A {
public:
    A(int a) : a(a) {}

    void print() {
        std::cout << "a=" << a << std::endl;
    }

private:
    int a;
};

int main() {
    auto p1 = std::make_shared<A>(10);
    p1->print();
    return 0;
}

上面的代码创建了一个类A的实例,并使用shared_ptr管理对象的内存。我们可以像使用原生指针一样来操作p1,包括调用成员函数和访问成员变量。当程序结束时,p1所占用的内存会自动释放。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++特性之智能指针shared_ptr详解 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 详解Matlab如何绘制圆角半透明图例

    如何绘制圆角半透明图例 在MATLAB中,我们可以使用legend函数来添加图例到绘图中。该函数允许设置图例框的不透明度,但默认情况下没有提供设置圆角的选项。但是,我们可以通过一些技巧来实现绘制圆角半透明图例。 以下是绘制圆角半透明图例的详细攻略: 设置图例不透明度 首先,我们可以通过设置图例的Alpha不透明度选项来使其变为半透明。以下代码演示如何使用Al…

    C 2023年5月23日
    00
  • 详细介绍Java关键字throw throws Throwable的用法与区别

    详细介绍Java关键字 throw, throws, Throwable 的用法与区别 在Java程序中,异常处理是必不可少的一部分。Java中的异常是指程序在执行过程中发生错误或异常情况时,根据不同的情况产生不同的异常信息。Java中有三个关键字:throw, throws, Throwable,它们是处理Java异常的重要工具。 throw关键字 thr…

    C 2023年5月23日
    00
  • C语言实现航班售票系统 C语言实现航班管理系统

    C语言实现航班售票系统/C语言实现航班管理系统 1. 系统需求分析 从乘客角度: 查询已有航班信息。 按起降时间、出发地、目的地、班次号等筛选符合需求的航班信息。 预定航班票。 取消预定航班票。 查看已预定航班票。 从航空公司角度: 增加、删除、修改航班信息。 航班出发前取消航班。 确认航班售票情况。 2. 功能设计 显示菜单,包括: 登录; 注册; 查询航…

    C 2023年5月30日
    00
  • 深入理解C语言的new[]和delete[]

    我可以为你详细讲解“深入理解C语言的new[]和delete[]”的完整攻略。 为什么需要new[]和delete[] 在C语言中,通常使用malloc和free函数来进行动态内存的分配和释放。而在C++中,有new和delete操作符来完成这个任务。其中,new和delete操作符不仅仅可以使用于基本数据类型的内存分配和释放,还能够使用于复杂数据类型的内存…

    C 2023年5月23日
    00
  • 利用idea搭建SSM项目看这一篇就够了

    以下是详细讲解“利用idea搭建SSM项目看这一篇就够了”的完整攻略,其中包含两个示例说明。 1. 确定开发环境 要开发SSM项目,需要先确定好我们的开发环境。我们需要安装以下软件: JDK:Java Development Kit。 Tomcat:Web服务器,用于部署项目。 MySQL:关系型数据库系统。 Maven:Java项目的构建工具。 IDEA:…

    C 2023年5月23日
    00
  • C++隐式类型转换运算符operator type()用法详解

    C++隐式类型转换运算符operator type()用法详解 隐式类型转换是 C++ 一个重要的特性,在某些情况下可以简化代码并方便编程。其中,使用 operator type() 运算符可以指定自定义类型转换规则。本文将详细讲解该运算符的用法。 语法 operator type() { /* … */ } 其中,type 指定了你希望将自定义类型转换…

    C 2023年5月22日
    00
  • C++中Operator类型强制转换成员函数解析

    Operator类型强制转换成员函数是C++中的一种特殊的成员函数,用于在自定义类型中实现类型转换。Operator类型强制转换成员函数可以将对象从一种类型转换为另一种类型。注意,Operator类型强制转换成员函数既可以定义为成员函数也可以定义为非成员函数。 在C++中,有六种Operator类型强制转换成员函数。它们分别是: const_cast dyn…

    C 2023年5月22日
    00
  • CentOS下Jsoncpp安装配置的方法

    首先,确保你已经安装了CentOS和GCC编译器。接下来,我们可以按照以下步骤进行Jsoncpp的安装配置。 安装Jsoncpp库 下载Jsoncpp库的最新稳定版本,在Github上可以找到下载链接,可以使用以下命令完成下载: $ wget https://github.com/open-source-parsers/jsoncpp/archive/1.9…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部