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日

相关文章

  • 从Immutable.js到Redux函数式编程

    从Immutable.js到Redux函数式编程的完整攻略包含以下步骤: 1. 简介 Immutable.js是一个JS库,提供了一组不可变数据结构集合(如List、Map、Set等),可以帮助我们更简洁、高效地处理数据,同时避免出错。而Redux是一个用于JavaScript应用程序的可预测状态容器,可以确保你的应用的行为始终一致且易于测试。借助Immut…

    C 2023年5月22日
    00
  • C语言实现图书馆管理系统

    C语言实现图书馆管理系统攻略 背景介绍 随着图书馆图书数量的不断增加,传统的人工管理方式已经越来越难以适应现代的需求,因此,采用计算机辅助手段实现图书馆管理是一个非常好的选择。下面我们将介绍如何使用C语言来实现一个图书馆管理系统。 系统功能 本系统主要包括以下功能: 图书信息的添加、删除、修改、查询 借书、还书功能 统计信息的查询 用户信息的添加、删除、修改…

    C 2023年5月23日
    00
  • C语言中打印特殊图案的实现代码

    下面是详细讲解“C语言中打印特殊图案的实现代码”的完整攻略。 1. 基本概念 在C语言中,我们可以通过使用转义字符来实现打印特殊字符或图案的功能。转义字符是以反斜杠(\)开头的一种特殊字符,它们表示某些无法输入的字符,如换行符、制表符、回车符等。 2. 实现代码 2.1 示例一:打印三角形 以下代码可以打印一个由星号组成的三角形,可以通过连续打印多行来实现。…

    C 2023年5月24日
    00
  • java抛出异常的几种情况小结

    让我详细讲解一下“Java抛出异常的几种情况小结”的完整攻略。 1. Java抛出异常的概念 Java中的异常是指在程序运行时发生了错误或异常情况而无法正常执行的情况。简单来说,当程序出现意料之外的错误或者问题,抛出异常是必须的。 2. Java异常的分类 Java异常可以分为两类:检查异常和非检查异常。 2.1 检查异常 当程序出现问题时,会产生一个检查异…

    C 2023年5月23日
    00
  • Go JSON编码与解码的实现

    Go JSON编码与解码的实现 在Go语言中,JSON编码与解码非常常见,Golang标准库提供了encoding/json包来支持JSON格式数据的序列化和反序列化。接下来将详细讲解如何使用encoding/json包进行JSON编码与解码。 JSON编码 JSON编码,指将Go语言中的结构体等数据类型转换成JSON格式的字符串。在Go语言中,使用json…

    C 2023年5月23日
    00
  • 神乐千鹤在拳皇97、98中的高级用法

    神乐千鹤在拳皇97、98中的高级用法攻略 什么是神乐千鹤? 神乐千鹤是拳皇系列游戏中的一位角色,拥有快速的移动速度和敏捷的攻击方式。她在拳皇97和98中的操作难度较高,但是如果掌握了她的高级用法,就可以轻松地击败对手。 神乐千鹤的高级用法 1. 投掷连击 神乐千鹤的投掷连击是一种非常强大的攻击方式。要进行投掷连击,首先需要进行一次投掷攻击(按下前+C),然后…

    C 2023年5月22日
    00
  • 剑网3明教怎么玩_剑网3明教贯木流PVE输出攻略(必看)

    剑网3明教怎么玩 简介 《剑网3》作为一款以武学为主题的MMORPG游戏,拥有多个门派供玩家选择。其中明教门派以其独树一帜的特点,备受玩家们的喜爱。本攻略将为大家介绍明教门派的PVE输出攻略,帮助各位玩家更好地在游戏中玩转明教职业。 明教门派的特点 明教门派主修内功心法,拥有较高的爆发输出和回复能力 明教的操作非常流畅,配合技能后摇短,能够进行多种连招输出 …

    C 2023年5月22日
    00
  • 约瑟夫环问题(数组法)c语言实现

    约瑟夫环问题(数组法)C语言实现 问题描述 有 $n$ 个人围成一圈,第 $m$ 个人开始报数,报到 $m$ 的人出圈,然后从出圈的下一个人开始继续报数,直到圈中只剩下一人。求出该人的编号。 解法思路 采用数组法解决约瑟夫环问题,主要的思路是:构建一个大小为 $n$ 的数组,来表示 $n$ 个人在约瑟夫环中的位置,将这些位置依次删除,直到只有一个人为止。 具…

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