C++11 标准库头文件模拟实现

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • ● 智能指针模板
  • ● Vector
    • 1. 简单版本
    • 2. X
  • 总结


前言

暂不考虑支持多线程
常用STL的简单实现,主要内容百行左右完成,意在理解STL的原理


● 智能指针模板

SharedPtr

在这里插入图片描述

#include <assert.h>
#include <atomic>template <class T>
class SharedPtr
{
public:typedef T element_type;explicit SharedPtr(T* ptr = nullptr) : m_ref(nullptr){if (ptr)  m_ref = new reftype(ptr);}template <class Deleter>explicit SharedPtr(T* ptr, Deleter d) : m_ref(nullptr){if (ptr) m_ref = new reftye_with_deleter<Deleter>(ptr, d);}SharedPtr(const SharedPtr& tocopy){Acquire(tocopy.m_ref);}~SharedPtr(){Release();}SharedPtr& operator=(const SharedPtr& tocopy){if (this != &tocopy){Release();Acquire(tocopy.m_ref);}return *this;}SharedPtr& operator=(T* ptr){if (get() != ptr){Release();if (ptr) m_ref = new reftype(ptr);}return *this;}T* get() const{return m_ref ? m_ref->m_ptr : nullptr;}void reset(T* ptr = nullptr){Release();if (ptr) m_ref = new reftype(ptr);}template <class Deleter>void reset(T* ptr, Deleter d){Release();if (ptr) m_ref = new reftye_with_deleter<Deleter>(ptr, d);}bool unique() const { return m_ref ? m_ref->m_count == 1 : true; }long use_count() const { return m_ref ? m_ref->m_count.load() : 0; }// test for pointer validity: defining conversion to unspecified_bool_type// and not more obvious bool to avoid implicit conversions to integer typestypedef T*(SharedPtr<T>::*unspecified_bool_type)() const;operator unspecified_bool_type() const{if (m_ref && m_ref->m_ptr) return &SharedPtr<T>::get;else nullptr;}T& operator*() const{assert(m_ref && m_ref->m_ptr);return *( m_ref->m_ptr);}T* operator->() const{assert(m_ref && m_ref->m_ptr);return m_ref->m_ptr;}private:struct reftype{reftype(T* ptr) : m_ptr(ptr), m_count(1) {}virtual ~reftype() {}virtual void delete_ptr() { delete m_ptr; }T*              m_ptr;std::atomic_int m_count;};template <class Deleter>struct reftye_with_deleter: public reftype{reftye_with_deleter(T* ptr, Deleter d) : reftype(ptr), m_deleter(d) {}virtual void delete_ptr() override{m_deleter(this->m_ptr);}Deleter m_deleter;};reftype* m_ref;void Acquire(reftype* ref){m_ref = ref;if (ref) ref->m_count.fetch_add(1);}void Release(){if (m_ref){if (! --m_ref->m_count ){m_ref->delete_ptr();delete m_ref;}m_ref = nullptr;}}
};template <class T, class U>
bool operator==(const SharedPtr<T>& a, const SharedPtr<U>& b)
{return a.get() == b.get();
}
template <class T, class U>
bool operator!=(const SharedPtr<T>& a, const SharedPtr<U>& b)
{return a.get() != b.get();
}//------------------------------------------------------------------------------
#include <iostream>
#include <stdio.h>
class TestSt
{
public:char buf[1024];char bux[4096];
public:TestSt() { printf("   const %p\n", this);};~TestSt(){printf("~TestSt: %p\n", this);}
};int main()
{std::atomic_int at;SharedPtr<TestSt> p_st(new TestSt());SharedPtr<TestSt> p_st2(p_st);SharedPtr<TestSt> p_st3(new TestSt());p_st3 = p_st2;std::cout << p_st.use_count() << " " << p_st2.use_count() << " " << p_st3.use_count() << " " <<  std::endl;}

● Vector

auto p = new T[N]; 申请空间,为每个元素p[i]调用T的构造函数
delete[] p; 先为每个元素调用析构函数,释放空间

1. 简单版本

在这里插入图片描述

new (m_values+i) T(val); 和 m_values[i] = val并不等价
当value_type包含虚函数时后者不能正确处理虚函数表指针,而前者却可以。这或许也是C和C++不兼容的证据?
在这里插入图片描述
如图所示,new (m_values+i) T(val)可以正确处理虚表指针,而m_values[i] = val的_vptr.TestSt = 0x0

#include <stdlib.h>
#include <algorithm>template <class T>
class Vector
{
private:T* m_values;size_t m_size, m_capacity;public:typedef T value_type;typedef T* iterator;Vector(): m_values(nullptr), m_size(0), m_capacity(0) {}~Vector(){for (size_t i = 0; i < m_size; i++){m_values[i].~T();}free(m_values);m_values = nullptr;m_size = m_capacity = 0;}Vector(size_t n, const T& val): m_values(nullptr), m_size(n),m_capacity(n){m_values =  (T*)malloc(sizeof(T) * m_capacity);for (size_t i = 0; i < n; i++){new (m_values+i) T(val);}}Vector(const Vector<T>& tocopy){m_values =  (T*)malloc(sizeof(T) * tocopy.m_capacity);m_size = tocopy.m_size;m_capacity = tocopy.m_capacity;for (size_t i = 0; i < m_size; i++){new (m_values+i) T(tocopy.m_values[i]);}}Vector<T>& operator=(const Vector<T>& tocopy){if (&tocopy == this) return *this;Vector<T> tmp(tocopy);std::swap(m_values, tmp.m_values);std::swap(m_size, tmp.m_size);std::swap(m_capacity, tmp.m_capacity);return *this;}value_type& operator[](size_t idx){return m_values[idx];}void push_back(const T& val){if (m_size + 1 > m_capacity){m_capacity = m_capacity ? 2*m_capacity : 1;T* tmp = (T*)malloc(sizeof(T) * m_capacity);for (size_t i = 0; i < m_size; i++){new (tmp+i) T(m_values[i]);m_values[i].~T();}free(m_values);m_values = tmp;}new (m_values+m_size) T(val);++m_size;}void pop_back(){--m_size;m_values[m_size].~T();}void clear(){for (size_t i = 0; i < m_size; i++){m_values[i].~T();}m_size = 0;}size_t size() { return m_size; }iterator begin(){return m_values;}iterator end(){return m_values + m_size;}
};

2. X


总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/858191.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

主数据驱动的数据治理:技术解析与实践探索

数字化转型行业小伙伴可以加入我的星球&#xff0c;初衷成为各位数字化转型参考库&#xff0c;星球内容每周更新 个人工作经验资料全部放在这里&#xff0c;包含数据治理、数据要素、数据质量、数据安全、元数据、主数据、企业架构、DCMM、DSMM、CDGA、CDGP等各种数据相关材料 …

抖音多功能全自动引流工具,支持评论关注私信留痕点赞等,让你的抖音粉丝暴涨!

随着短视频行业的火爆&#xff0c;越来越多的人开始关注抖音这个平台。然而&#xff0c;如何在抖音上获得更多的关注和粉丝&#xff0c;成为了许多人面临的难题。为了帮助大家解决这个问题&#xff0c;今天我们将为大家推荐一款抖音多功能全自动引流脚本&#xff0c;这款脚本可…

HarmonyOS SDK助力鸿蒙原生应用“易感知、易理解、易操作”

6月21-23日&#xff0c;华为开发者大会&#xff08;HDC 2024&#xff09;盛大开幕。6月23日上午&#xff0c;《HarmonyOS开放能力&#xff0c;使能应用原生易用体验》分论坛成功举办&#xff0c;大会邀请了多位华为技术专家深度解读如何通过根技术、开放能力、场景化控件等亮点…

vue3 antdv Select 实现输入关键词,通过服务器去查询数据,并显示到表格中的实现思路。

实现思路&#xff1a; 1&#xff09;输入关键词&#xff0c;通过Select的查询事件&#xff08;onSearch&#xff09;来到服务器查询数据。 2&#xff09;根据查询到的数据显示到表格中&#xff0c;然后通过表格的&#xff08;cellClickEvent&#xff09;事件来选择相关的用户…

Python武器库开发-武器库篇之ThinkPHP 5.0.23-RCE 漏洞复现(六十四)

Python武器库开发-武器库篇之ThinkPHP 5.0.23-RCE 漏洞复现&#xff08;六十四&#xff09; 漏洞环境搭建 这里我们使用Kali虚拟机安装docker并搭建vulhub靶场来进行ThinkPHP漏洞环境的安装&#xff0c;我们进入 ThinkPHP漏洞环境&#xff0c;可以 cd ThinkPHP&#xff0c;然…

嵌入式学习——数据结构(队列)——day50

1. 查找二叉树、搜索二叉树、平衡二叉树 2. 哈希表——人的身份证——哈希函数 3. 哈希冲突、哈希矛盾 4. 哈希代码 4.1 创建哈希表 4.2 5. 算法设计 5.1 正确性 5.2 可读性&#xff08;高内聚、低耦合&#xff09; 5.3 健壮性 5.4 高效率&#xff08;时间复杂度&am…

【Java】pcm 与 wav 格式互转工具类 (附测试用例)

文章目录 1. 前言1.1 背景1.2 目标1.3 亮点 2. 用例说明3. 补充验证4. 相关链接 1. 前言 git 仓库 https://github.com/ChenghanY/pcm-wav-converter 1.1 背景 系统新接入语音引擎。 语音引擎只认 pcm 格式数据。前端只认 wav 格式 。 需要后端对 pcm 和 wav 格式实现互转&a…

2.超声波测距模块

1.简介 2.超声波的时序图 3.基于51单片机实现的代码 #include "reg52.h" #include "intrins.h" sbit led1P3^7;//小于10&#xff0c;led1亮&#xff0c;led2灭 sbit led2P3^6;//否则&#xff0c;led1灭&#xff0c;led2亮 sbit trigP1^5; sbit echo…

Adobe XD最新2023资源百度云盘下载(附教程)

如大家所了解的&#xff0c;Adobe XD是一种基于矢量的UI和UX设计工具&#xff0c;可用于设计从智能手表应用程序到成熟网站的任何内容&#xff0c;功能非常强大且操作便捷。目前最新已推出2023版本。 Adobe XD解决了Photoshop和其他图形应用程序无法解决的两个主要问题&#xf…

vue 中实现用户上传文件夹的功能

vue 中实现上传文件夹的功能 使用 input 元素的 webkitdirectory 属性使用 vue-simple-uploader 组件 vue 中文件上传一般都是用 element 中的 upload 组件&#xff0c;upload 组件可以实现单个文件或者多个文件的上传&#xff0c;但是无法通过选择文件夹上传其中文件。 要实现…

八爪鱼现金流-030,升级日志

八爪鱼现金流 八爪鱼 2024年4月4日09:27:02 v-0.0.1 资产包、负债包&#xff0c;功能优化 2024年4月15日09:27:26 v-0.0.2 增加公告模块 2024年4月18日12:14:32 v-0.0.3 市场查询优化。创建人脱敏处理。增加市场风云菜单。 2024年4月18日15:57:10 v-0.0.4 对于无截止日…

如何自制一个Spring Boot Starter并推送到远端公服

在现代Java开发中&#xff0c;Spring Boot无疑是一个强大且便捷的框架&#xff0c;它通过提供大量的Starter来简化依赖管理和项目配置。有时&#xff0c;我们可能需要为特定功能或团队定制Starter。本文将指导你如何创建自己的Spring Boot Starter并将其推送到远程公共服务器上…

Pwn刷题记录(不停更新)

1、CTFshow-pwn04&#xff08;基础canary&#xff09; ​ 好久没碰过pwn了&#xff0c;今天临时做一道吧&#xff0c;毕竟刚联合了WSL和VSCode&#xff0c;想着试着做一道题看看&#xff0c;结果随手一点&#xff0c;就是一个很少接触的&#xff0c;拿来刷刷&#xff1a; ​ …

ClosedXML

一、类库介绍 ClosedXML是一个用于读取、操作和写入Excel 2007 (.xlsx, .xlsm)文件的.NET第三方库。它基于OpenXML&#xff0c;但与OpenXML相比&#xff0c;ClosedXML具有更高的性能和更易于使用的API接口。 ClosedXML支持XML文档的解析和生成&#xff0c;可以处理复杂的XML结…

STL迭代器的应用

STL迭代器的应用 迭代器的定义方法&#xff1a; 类型作用定义方式正向迭代器正序遍历STL容器容器类名::iterator 迭代器名常量正向迭代器以只读方式正序遍历STL容器容器类名::const_iterator 迭代器名反向迭代器逆序遍历STL容器容器类名::reverse_iterator 迭代器名常量反向迭…

使用Spring Boot构建全栈应用程序:从理论到实践

文章目录 引言第一章 项目初始化1.1 使用Spring Initializr生成项目1.2 创建基本项目结构 第二章 后端服务开发2.1 定义实体类2.2 创建Repository接口2.3 实现Service类2.4 创建Controller类 第三章 前端集成3.1 使用Thymeleaf模板引擎3.2 创建前端控制器 第四章 安全配置4.1 S…

如何解决vue中的路由守卫失效问题

引言 1. 路由守卫简介 路由守卫是前端开发中一个至关重要的概念&#xff0c;特别是在使用单页应用&#xff08;SPA&#xff09;框架如React、Vue或Angular时。它们充当了SPA中的“门卫”&#xff0c;控制着用户对不同页面的访问权限。路由守卫的核心功能是确保用户在访问特定…

迅狐多商户直播商城系统源码:电商领域的创新融合

随着直播技术的兴起和电子商务的蓬勃发展&#xff0c;迅狐多商户直播商城系统源码应运而生&#xff0c;为商家和消费者提供了一个全新的互动购物平台。 多商户直播商城系统源码概述 迅狐多商户直播商城系统源码是一个高度集成的解决方案&#xff0c;它结合了直播的即时性和电…

C语言的数据结构:树与二叉树(树篇)

前言 之前所学到的数据结构都是线性结构特征&#xff0c;所谓线性就是在结构上&#xff0c;将节点连接起来时&#xff0c;像一条线一样。如链表则是上一个节点包含下一个节点地址的指针&#xff0c;这样依次下去。而串、队列、栈则实现方式都依赖于链表或顺序表而实现&#xf…

报错:mAP数据为0%+无法读取output里的图片红色警告

debug检查&#xff1a;发现创建的output和input的路径不在同一级 操作1&#xff1a;修改output创建路径为绝对路径后&#xff0c;output和input文件成功在同一级&#xff0c;但问题仍存在 debug检测&#xff1a;识别的类别和保存的类别不同&#xff0c;没有保存数据 操作2&…