c++11 新特性——智能指针使用详解

C++11 新特性——智能指针使用详解

在C++中,内存管理一直是一个非常重要的事情,一个常见的错误就是忘记释放先前分配的内存。C++11引入了智能指针,从而使得内存管理更加方便。本文将详细介绍智能指针的使用方法。

智能指针概述

C++中的智能指针是一种RAII(Resource Acquisition Is Initialization)机制的实现,它通过对象生命周期的结束来自动释放分配的内存。

在C++11中,常见的智能指针有两种:std::unique_ptr和std::shared_ptr。下面将分别详细说明它们的用法。

std::unique_ptr

std::unique_ptr是一种独占所有权的智能指针。它保证同时只有一个指针可以指向被分配的内存,并且在它被销毁时会自动释放这个内存,即可以避免内存泄漏。

unique_ptr的定义和初始化

std::unique_ptr的定义样式如下:

std::unique_ptr<type> ptr_name(new type(args));

其中,type为要分配内存的类型,ptr_name为指向该类型对象的智能指针,new type(args)用于分配堆内存并返回该堆内存的地址。

下面是一个示例:

std::unique_ptr<int> p(new int(10));

这个语句创建了一个指向int类型对象的智能指针p,并将值为10的整数存放在指针指向的内存位置。

unique_ptr的拷贝和移动

由于std::unique_ptr是独占所有权的,因此它不能被其他指针指向。但是,我们可以使用std::move函数将其转移给另一个unique_ptr。如下所示:

std::unique_ptr<int> p1(new int(10));
std::unique_ptr<int> p2(std::move(p1));

这个语句创建了两个指向int类型对象的智能指针p1和p2,其中p2是通过std::move函数从p1转移而来的。

值得注意的是,由于唯一所有权,std::unique_ptr是不能被拷贝的。以下代码会导致编译错误:

std::unique_ptr<int> p1(new int(10));
std::unique_ptr<int> p2(p1); // 编译错误

unique_ptr的使用

std::unique_ptr的使用方法与普通指针类似,可以使用*或->操作符来访问其所指向的对象,如下所示:

std::unique_ptr<int> p(new int(10));
std::cout << *p << std::endl;

这个语句输出p指向的int类型对象的值,即10。

除此之外,std::unique_ptr还提供了release函数和reset函数。

release函数用于将std::unique_ptr中的指针地址返回并释放所有权。下面是一个示例:

std::unique_ptr<int> p(new int(10));
int* ptr = p.release();

这个语句将p中的指针地址释放,并将其返回给变量ptr。

reset函数用于释放当前指向的对象,并将指针指向新对象。下面是一个示例:

std::unique_ptr<int> p(new int(10));
p.reset(new int(20));
std::cout << *p << std::endl;

这个语句释放p指向的int类型对象,并将p指向一个新的地址,该地址存放了值为20的整数。

std::shared_ptr

std::shared_ptr是一种共享所有权的智能指针。它可以使多个指针指向同一块内存,并可以在最后一个指针被销毁时自动释放该内存,避免了内存泄露。

shared_ptr的定义和初始化

std::shared_ptr的定义样式如下:

std::shared_ptr<type> ptr_name(new type(args));

其中,type为要分配内存的类型,ptr_name为指向该类型对象的智能指针,new type(args)用于分配堆内存并返回该堆内存的地址。

下面是一个示例:

std::shared_ptr<int> p1(new int(10));
std::shared_ptr<int> p2 = p1; // p2和p1共享所有权

这个语句创建了两个指向int类型对象的智能指针p1和p2,其中p2是从p1拷贝而来的。由于std::shared_ptr是共享所有权的,因此p1和p2指向同一个int类型对象,并且在这两个指针被销毁时,它们会自动释放该内存。

shared_ptr的使用

std::shared_ptr的使用方法与普通指针类似,可以使用*或->操作符来访问其所指向的对象,如下所示:

std::shared_ptr<int> p(new int(10));
std::cout << *p << std::endl;

这个语句输出p指向的int类型对象的值,即10。

除此之外,std::shared_ptr还提供了一个use_count函数,用于返回当前有多少个智能指针指向该对象。下面是一个示例:

std::shared_ptr<int> p1(new int(10));
std::shared_ptr<int> p2 = p1;
std::cout << "The use count is " << p1.use_count() << std::endl; // 输出2

这个语句输出指向int类型对象的智能指针的个数,即2。

示例

下面是一个使用std::unique_ptr的示例,用于分配包含两个字符串的结构。

struct test
{
    std::string str1;
    std::string str2;
    test() : str1(""), str2("") { }
    test(const std::string& s1, const std::string& s2) : str1(s1), str2(s2) { }
};

int main()
{
    std::unique_ptr<test> ptest(new test("Hello", "world"));
    std::cout << ptest->str1 << ", " << ptest->str2 << std::endl;

    return 0;
}

这段代码首先定义了一个结构体test,其包含两个string类型的成员变量str1和str2。然后,通过std::unique_ptr分配一个test类型的对象,其中使用了结构体构造函数初始化了它的两个成员变量。最后,通过unique_ptr的->操作符访问了该结构体的成员变量,并将它们输出到终端上。

下面是一个使用std::shared_ptr的示例,用于模拟对象间的引用:

#include <iostream>
#include <memory>

class test;

void func(std::shared_ptr<test> p);

class test
{
public:
    test() { std::cout << "test is constructed" << std::endl; }
    ~test() { std::cout << "test is destructed" << std::endl; }
    void func(std::shared_ptr<test> p)
    {
        std::cout << "test's func is called" << std::endl;
    }
};

void func(std::shared_ptr<test> p)
{
    std::cout << "func is called" << std::endl;
    p->func(p);
}

int main()
{
    std::shared_ptr<test> p1(new test());
    func(p1);

    return 0;
}

这个代码模拟了两个对象,它们之间相互引用。该示例中,通过std::shared_ptr分配了一个test类型的对象,并将其传递给func函数。在func函数中,使用std::shared_ptr调用了test类的成员函数func,并将该智能指针作为参数传递给了该函数。

在这个示例中,由于使用了std::shared_ptr,因此两个对象之间的引用始终保持着,并且在所有引用被销毁时,它们指向的内存会被自动释放,从而避免了内存泄漏。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++11 新特性——智能指针使用详解 - Python技术站

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

相关文章

  • IOS中Json解析实例方法详解(四种方法)

    这里给您详细讲解“IOS中Json解析实例方法详解(四种方法)”的完整攻略。 简介 iOS应用中,我们有时需要从服务器端获取JSON数据,这时我们就需要对JSON数据进行解析。本篇文章将详细介绍iOS中JSON解析的四种方法。 方法一:NSJSONSerialization NSJSONSerialization是iOS 5.0之后提供的解析JSON数据的类…

    C 2023年5月23日
    00
  • 最短时间学会基于C++实现DFS深度优先搜索

    最短时间学会基于C++实现DFS深度优先搜索攻略 什么是DFS深度优先搜索 DFS即深度优先搜索,是一种基于搜索算法的遍历和检索树或图数据结构的算法。DFS算法采用深度优先策略,从根结点出发访问所有可达结点,直到叶子节点。在访问某个结点时,先访问该结点的第一个未访问的相邻节点,然后递归的访问其非相邻节点。其搜索的核心思想是根据某个搜索方向向前搜索到底,直至无…

    C 2023年5月22日
    00
  • TPLINK XTR5466内置天线款路由器怎么样? xtr5466c拆解评测

    TPLINK XTR5466内置天线款路由器评测攻略 1. 设备介绍 TPLINK XTR5466是一款内置天线的路由器,采用4×4 MU-MIMO技术,可以同时支持多台设备的数据传输。拥有5个千兆以太网口、1个USB 3.0接口、1个USB 2.0接口,适用于家庭或办公室等小型网络环境。 2. 性能测试 2.1 信号覆盖范围测试 采用普通笔记本电脑连接,分…

    C 2023年5月23日
    00
  • 十个C++恶搞朋友的代码合集

    这篇攻略会对“十个C++恶搞朋友的代码合集”进行详细讲解,介绍每个代码的用途和实现方式。以下是每个代码及其说明: 1. 静态断言 这个文件定义了一个静态断言的宏 static_assert(),如果编译器在编译过程中发现了 false 的表达式,那么编译将失败。以下是一个示例: static_assert(sizeof(int) == 8, "in…

    C 2023年5月24日
    00
  • Python操作MySQL MongoDB Oracle三大数据库深入对比

    Python操作MySQL MongoDB Oracle三大数据库深入对比 本文将介绍如何使用Python对MySQL、MongoDB和Oracle三大数据库进行操作,并从安装、连接、基本操作、性能等多个方面进行深入对比。 环境配置 MySQL 首先需要安装MySQL数据库,可以去官网下载MySQL Installer,然后按照指引完成安装。 安装完成后,需…

    C 2023年5月23日
    00
  • 一文详解C++中动态内存管理

    一文详解C++中动态内存管理 什么是动态内存 在C++中,内存是分为静态和动态两种。静态内存是在程序编译时就已经分配好的,而动态内存指的则是在程序运行时动态分配的内存。 动态内存管理在C++编程中非常重要,我们通常使用new和delete关键字进行动态内存的分配和释放。这种方式相比静态内存分配,可以更灵活地控制内存的使用情况。 动态内存分配 在C++中,动态…

    C 2023年5月23日
    00
  • php 读写json文件及修改json的方法

    下面给出 PHP 读写 JSON 文件并修改 JSON 的方法的详细攻略。 一、读取 JSON 文件 PHP 中可以使用 json_decode 函数来读取 JSON 文件,将 JSON 字符串转化为 PHP 中的数组或对象。 示例代码如下: $file_path = "test.json"; $json_string = file_ge…

    C 2023年5月23日
    00
  • C++简单实现shared_ptr的代码

    实现一个简单的shared_ptr需要考虑以下几个方面: 1.计数器实现:将指针的计数器放在一个自定义类中,当有多个shared_ptr指向同一个对象时,计数器加1;当一个指针被销毁时,计数器减1;当计数器为0时,释放对象所占用的内存。 2.拷贝构造函数和赋值运算符实现:在拷贝构造函数和赋值运算符中,需要将新对象的计数器指向原对象的计数器,使得两个对象指向同…

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