C++简单实现shared_ptr的代码

yizhihongxing

实现一个简单的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日

相关文章

  • Qt利用QJson实现解析数组的示例详解

    以下是“Qt利用QJson实现解析数组的示例详解”的完整攻略: 1. 引入QJson库 在Qt项目中使用QJson,需要在.pro文件中添加以下代码引入QJson库: QT += network LIBS += -lqjson 2. 解析JSON字符串 使用QJson库进行解析,首先需要将JSON字符串转成QJsonDocument类型,然后调用QJsonD…

    C 2023年5月23日
    00
  • Qt如何设置窗口屏幕居中显示以及设置大小

    关于Qt如何设置窗口屏幕居中显示以及设置大小,以下是一份完整攻略: 设置窗口居中 如果我们想让Qt应用程序中的窗口在启动时居中显示,可以按照以下步骤操作: 获取屏幕的Geometry:cpp QDesktopWidget* desktop = QApplication::desktop(); QRect screen = desktop->screen…

    C 2023年5月23日
    00
  • C语言实现职工工资管理系统的示例代码

    下面是对于“C语言实现职工工资管理系统的示例代码”的完整攻略,包含了过程、示例说明以及代码实现: 1. 需求分析 该工资管理系统主要包括以下功能: 录入职工信息 查询职工信息 删除职工信息 修改职工信息 计算职工工资 根据上述需求,我们可以将职工信息抽象为一个结构体,包括工号、姓名、性别、年龄、基本工资等成员变量。通过调用各种函数实现各项功能,并将所有信息存…

    C 2023年5月23日
    00
  • 全境封锁2武器有哪些 全武器介绍

    全境封锁2武器有哪些 全武器介绍 全境封锁2是一款以军事背景为主题的 RPG 游戏,其中武器种类丰富。本文将对这些武器进行全面介绍。 武器种类 全境封锁2中的武器大致可分为以下几类: 步枪 冲锋枪 狙击枪 轻机枪 战斗霰弹枪 手枪 火焰喷射器 黄金枪 不同武器介绍 步枪 步枪是一类长枪,常见的有 AK47、M16A2 等。通常适用于中远距离作战,威力较大,但…

    C 2023年5月22日
    00
  • 详解C/C++中低耦合代码的设计实现

    详解C/C++中低耦合代码的设计实现 在C/C++开发过程中,低耦合的代码设计和实现可以提高代码的可读性、可维护性和可重用性,更加适合大型项目的开发。下面我们将详细讲解如何实现低耦合的代码设计。 1. 引入头文件的精简化 在编写C/C++代码的时候,我们会引入许多头文件,这些头文件中可能包含了许多不必要的定义和声明。这些不必要的定义和声明会增加代码的耦合度。…

    C 2023年5月30日
    00
  • SpringMVC JSON数据交互及RESTful支持实现方法

    下面是详细讲解“SpringMVC JSON数据交互及RESTful支持实现方法”的完整攻略。 SpringMVC JSON数据交互及RESTful支持实现方法 什么是JSON JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于 JavaScript 的一个子集。JSON采用完全独立于语言的文本格式,因此可…

    C 2023年5月23日
    00
  • Java日常练习题,每天进步一点点(30)

    Java日常练习题是一套帮助Java初学者巩固基础的练习题目,目的是帮助学习者每天进行一点点的练习,逐步提高自己的编程技能。 本套练习共包含30个题目,其中每个题目都涵盖了不同的知识点,涉及数据结构、算法、面向对象编程以及Java开发中的实践等。下面,我们将通过以下步骤来详细讲解Java日常练习题的攻略: 步骤一:理解题意 在开始每个练习题之前,首先需要仔细…

    C 2023年5月23日
    00
  • 详解Android JNI的基本使用(CMake)

    下面我来详细讲解一下“详解Android JNI的基本使用(CMake)”的完整攻略。 什么是 JNI JNI(Java Native Interface)是Java提供的一套编程规范,用于在Java和C/C++之间进行互操作。通过使用JNI,我们可以在Java代码中调用C/C++实现的函数,并且可以将Java对象转换为C/C++中对应的数据类型,实现跨语言…

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