C++简单实现shared_ptr的代码

实现一个简单的shared_ptr需要考虑以下几个方面:

1.计数器实现:将指针的计数器放在一个自定义类中,当有多个shared_ptr指向同一个对象时,计数器加1;当一个指针被销毁时,计数器减1;当计数器为0时,释放对象所占用的内存。

2.拷贝构造函数和赋值运算符实现:在拷贝构造函数和赋值运算符中,需要将新对象的计数器指向原对象的计数器,使得两个对象指向同一个计数器。同时,需要保证原计数器的值加1,新计数器的值等于原计数器的值。

以下是实现shared_ptr的示例代码:

template<typename T>
class shared_ptr {
public:
  // 构造函数
  shared_ptr(T* ptr = nullptr) {
    if (ptr) {
      data = new Counter(ptr);
    }
  }

  // 拷贝构造函数
  shared_ptr(const shared_ptr<T>& ptr) {
    data = ptr.data;
    if (data) {
      data->counter++;
    }
  }

  // 赋值运算符
  shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
    if (this != &ptr) {
      release();
      data = ptr.data;
      if (data) {
        data->counter++;
      }
    }
    return *this;
  }

  // 重载*运算符
  T& operator*() const {
    return *(data->ptr);
  }

  // 重载->运算符
  T* operator->() const {
    return data->ptr;
  }

  // 获取计数器
  int use_count() const {
    if (data) {
      return data->counter;
    } else {
      return 0;
    }
  }

  // 释放指针,如果计数器为0,则删除对象
  void release() {
    if (data) {
      data->counter--;
      if (data->counter == 0) {
        delete data;
      }
    }
    data = nullptr;
  }

  // 析构函数
  ~shared_ptr() {
    release();
  }
private:
  struct Counter {
    Counter(T* p = nullptr) : ptr(p), counter(1) {}
    ~Counter() { delete ptr; }
    T* ptr;
    int counter;
  };
  Counter* data;
};

示例1:使用shared_ptr共享指针

#include <iostream>
#include "shared_ptr.h"

class MyClass {
public:
    MyClass() { std::cout << "MyClass()" << std::endl; }
    ~MyClass() { std::cout << "~MyClass()" << std::endl; }
};

int main() {
    shared_ptr<MyClass> p1(new MyClass); // 创建p1
    shared_ptr<MyClass> p2(p1); // 复制构造函数,p1、p2计数器都为2
    std::cout << "p1 use_count: " << p1.use_count() << std::endl; 
    std::cout << "p2 use_count: " << p2.use_count() << std::endl; 
    shared_ptr<MyClass> p3 = p1; // 赋值运算符,p1、p2、p3计数器都为3
    std::cout << "p1 use_count: " << p1.use_count() << std::endl; 
    std::cout << "p2 use_count: " << p2.use_count() << std::endl; 
    std::cout << "p3 use_count: " << p3.use_count() << std::endl; 
    return 0; // 离开作用域,p1、p2、p3计数器都为0,MyClass会被自动释放
}

输出:

MyClass()
p1 use_count: 2
p2 use_count: 2
p1 use_count: 3
p2 use_count: 3
p3 use_count: 3
~MyClass()

示例2:shared_ptr数组

#include <iostream>
#include "shared_ptr.h"

class MyClass {
public:
    MyClass(int n) : data(new int[n]) { std::cout << "MyClass()" << std::endl; }
    ~MyClass() { delete[] data; std::cout << "~MyClass()" << std::endl; }
    int* data;
};

int main() {
    shared_ptr<MyClass[]> p1(new MyClass[3](5)); // 创建包含3个MyClass对象的数组
    std::cout << "p1[1].data[2]: " << p1[1].data[2] << std::endl; // 访问数组
    return 0; // 离开作用域,MyClass数组会被自动释放
}

输出:

MyClass()
MyClass()
MyClass()
p1[1].data[2]: 5
~MyClass()
~MyClass()
~MyClass()

这里需要注意的是,shared_ptr的数组版本需要将单个类型的模板参数改为数组类型的模板参数,然后通过重载下标运算符来访问数组元素。同时,数组需要使用new[]开辟空间,使用delete[]释放空间。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++简单实现shared_ptr的代码 - Python技术站

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

相关文章

  • SQL SERVER 将XML变量转为JSON文本

    下面是SQL SERVER将XML变量转为JSON文本的完整攻略: 1. 首先将XML变量转为NVARCHAR类型 将XML变量使用CAST或CONVERT函数转换为NVARCHAR类型,方便后续JSON文本的生成。如下所示: DECLARE @xml XML='<student><name>Tom</name><a…

    C 2023年5月23日
    00
  • Perl 函数集小结

    Perl 函数集小结 – 完整攻略 什么是 Perl 函数 Perl 函数是一段可重复使用的代码,用于实现某个具体的功能。Perl 中的函数通常带有参数,有时会返回值。Perl 函数通常需要先定义后使用。 Perl 函数的定义 在 Perl 中定义函数的语法如下: sub function_name { # 函数体 } 其中,function_name 为函…

    C 2023年5月23日
    00
  • vscode插件设置之Golang开发环境配置全过程

    VS Code插件设置之Golang开发环境配置全过程 为什么需要配置Golang开发环境 Golang 是一种高效、可靠、快速和简单的编程语言,适用于Web开发以及云计算领域等。 在进行Golang项目开发时,需要搭建相应的开发环境,其中包括对Golang语言的了解,安装Golang编译器、配置编译器环境等。本文将为大家讲解VS Code插件设置之Gola…

    C 2023年5月23日
    00
  • C语言实现简单的图书管理系统

    C语言实现简单的图书管理系统攻略 一、前期准备 在实现图书管理系统之前,需要先了解以下基础知识: 结构体的定义和使用 文件的读写操作 指针的使用 掌握以上基础知识,才能顺利实现图书管理系统。 二、功能需求 我们要实现的图书管理系统需要以下功能模块: 添加图书信息(包括图书名称、作者、价格等信息) 删除图书信息 修改图书信息 查找图书信息 显示所有图书信息 三…

    C 2023年5月22日
    00
  • C++中引用的相关知识点小结

    C++中引用是一个非常重要的概念,使用它可以有效地提高代码的可读性和性能。本文将介绍引用的相关知识点,并通过示例说明如何使用引用。 引用的概念和基本语法 引用是一个已经存在的变量的别名,通过这个别名可以访问到这个变量的值。在C++中,通过在变量名前加“&”符号来定义一个引用。例如: int a = 1; int& b = a; 这里的“b”就…

    C 2023年5月22日
    00
  • 如何修复Win11/10坏图像错误0xc0000020?

    当Win11/10出现坏图像错误0xc0000020时,可能是由于您的显卡驱动程序损坏或未正确安装。下面是完整的修复步骤: 步骤1:重新安装显卡驱动程序 1.打开设备管理器,展开“显示适配器”选项。 2.右击显示适配器,选择“卸载设备”。 3.下载并安装最新版本的显卡驱动程序,可以在厂商官网下载。 4.安装完成后,重启计算机,检查错误是否消失。 步骤2:运行…

    C 2023年5月23日
    00
  • C语言中如何进行编译器选项设置?

    C语言编译器的选项设置可以通过命令行选项或者Makefile文件来实现。 命令行选项设置 使用命令行选项可以在编译时指定编译器的选项。以下是一些常用的选项及其解释: -c:将源文件编译为目标文件。 -o file:指定输出文件名字为file。 -I path:指定头文件的查找路径。 -L path:指定库文件的查找路径。 -l lib:链接名为lib的库文件…

    C 2023年4月27日
    00
  • C++版图书管理系统

    下面我就为大家详细讲解一下使用C++编写图书管理系统的完整攻略。我们将会涵盖整个实现过程,包括构建UI界面、实现数据读取与存储、实现添加、删除、查询和修改功能等。 构建UI界面 为了构建UI界面,我们需要使用C++中的图形界面库。在此,我们选择使用QT库。QT库是跨平台的图形开发框架,可以在Windows、Mac和Linux等操作系统上使用。最新的QT版本是…

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