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 types
    typedef 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


总结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c#使用自带库对字符串进行AES加密、解密

文章目录 1 代码1.1 定义Aes加密类块1.2 在主函数中调用 2 获取Key和IV2.1 基本方法2.2 自定义Key2.3 技术方面的原理 参考文章&#xff1a; C#软件加密实例&#xff1f; 。 参考官文&#xff1a; Aes 类。 在使用C#的自带的System.Security.Cryptography.Aes模块进行加密和解…

图的学习.

目录 一、图的基本概念 1.1图的种类 1.2顶点的度、入度和出度 1.3边的权和网 1.4路径、路径长度和回路 二、图的存储结构 2.1邻接矩阵法 2.2邻接表法 2.3十字链表 2.4邻接多重表 三、图的遍历 3.1广度优先搜索 3.2深度优先搜索 四、图的应用 4.1最小生成树 4.1.…

密码没有未来

无密码认证的好处 引领无密码未来之路万能钥匙 英国通过具体法律打击可预测密码 强密码是抵御网络威胁的第一道防线 如何破解价值百万美元的加密钱包密码 复制此链接到微信打开阅读全部以发布文章 新 GPU 在不到一小时内打开了网络上 59% 的密码。 现代计算机的能力不断增…

AGV机器人的调度开发分析(1)- 内核中的路线规划

准备开始写一个系列&#xff0c;介绍下AGV机器人的调度的开发和应用。 按照openTCS的核心内容&#xff0c;国内多家广泛应用于AGV的调度。那么架构图如下&#xff1a; Kernel中有一个是Routing&#xff0c;这是路由规划模块&#xff0c;需要实现的细节功能包括如下&#xff1a…

cesium 包络线

cesium 包络线 以下为源码直接复制可用 1、实现思路 通过turf.js中union方法来计算包络线官方地址:https://turfjs.fenxianglu.cn/ 闪烁线请查看cesium轨迹线(闪烁轨迹线) 2、示例代码 <!DOCTYPE html> <html lang="en"&g

Pwn刷题记录(不停更新)

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

计算机组成原理 —— 存储系统(DRAM和SRAM,ROM)

计算机组成原理 —— 存储系统&#xff08;DRAM和SRAM&#xff09; DRAM和SRAMDRAM的刷新DRAM地址复用ROM&#xff08;Read-Only Memory&#xff08;只读存储器&#xff09;&#xff09; 我们今天来看DRAM和SRAM&#xff1a; DRAM和SRAM DRAM&#xff08;动态随机存取存储器&…

springboot 酒庄内部管理系统(源码+sql+论文)

绪论 1.1 系统研究目的意义 随着信息技术的不断发展&#xff0c;我们现在已经步入了信息化的时代了&#xff0c;而信息时代的代表便是网络技术的日渐成熟&#xff0c;而现在网络已经和我们的生活紧密的联系起来了&#xff0c;我们不敢想象没有网络我们的生活会像怎么样&#…

六、资产安全—数据管理(CISSP)

目录 1.学习目标 2.数据管理最佳参考实践 3.数据质量维度:DAMA 4.数据生命周期控制 5.数据净化方式 6.生命周期安全控制 7.EOL、EOS、EOSL 1.学习目标 2.数据管理最佳参考实践 数据策略: 角色与责任: 数据所有权:

数据分析必备:一步步教你如何用matplotlib做数据可视化(10)

1、Matplotlib 二维箭头图 箭头图将速度矢量显示为箭头&#xff0c;其中分量(u&#xff0c;v)位于点(x&#xff0c;y)。 quiver(x,y,u,v)上述命令将矢量绘制为在x和y中每个对应元素对中指定的坐标处的箭头。 参数 下表列出了quiver()函数的参数 - x - 1D或2D阵列&#xff0c;…

C语言中的进制转换

基础概念 进制又称数制&#xff0c;是指用一组固定的符号和统一的规则来表示数值的方法&#xff0c;在C语言中&#xff0c;可以使用不同的前缀来表示不同的进制&#xff1a; 二进制&#xff1a;以0b或0B为前缀&#xff08;部分编译器可能不支持&#xff09;八进制&#xff1a…

Go日常分享 - error类型是指针类型吗?

背景 这个问题的产生来源于小泉在开发rpc接口时返回error遇到的问题&#xff0c;开发时想在defer里对err进行最终的统一处理赋值&#xff0c;发现外层接收一直都未生效。问题可以简化为成下面的小demo。 func returnError() error {var err errordefer func() {//err errors…

物联网系统运维——数据库部署

一.MySQL 1.概要 MySQL是一种关联数据库管理系统&#xff0c;关联数据:而不是将所有数据放在一个大仓库内&#xff0c;这样就增加了速度并提高了灵活性库将数据保存在不同的表中。性能高、成本低、可靠性好&#xff0c;已经成为最流行的开源数据库。 二.MySQL安装与配置 1. …

38.MessageToMessageCodec线程安全可被共享Handler

handler被注解@Sharable修饰的。 这样的handler,创建一个实例就够了。例如: ByteToMessageCodec的子类不能被@Sharable修饰 如果自定义类是MessageToMessageCodec的子类就是线程共享的,可以被@Sharable修饰的 package com.xkj.protocol;import com.xkj.message.Message; i…

浙大宁波理工学院2024年成人高等继续教育招生简章

浙大宁波理工学院&#xff0c;这所承载着深厚学术底蕴和卓越教育理念的学府&#xff0c;正热烈开启2024年成人高等继续教育的招生之门。这里&#xff0c;是知识的殿堂&#xff0c;是智慧的摇篮&#xff0c;更是您实现个人梦想、追求更高境界的起点。 ​浙大宁波理工学院始终坚…

[最全]设计模式实战(一)UML六大原则

UML类图 UML类图是学习设计模式的基础,学习设计模式,主要关注六种关系。即:继承、实现、组合、聚合、依赖和关联。 UML类图基本用法 继承关系用空心三角形+实线来表示。实现接口用空心三角形+虚线来表示。eg:大雁是最能飞的,它实现了飞翔接口。 关联关系用实线箭头来表示…

基础算法---滑动窗口

文章目录 什么是滑动窗口1.长度最小的子数组2.无重复字符的最长子串3.最大连续1的个数4.将x减到0的最小操作数5.最小覆盖子串总结 什么是滑动窗口 滑动窗口&#xff08;Sliding Window&#xff09;是一种在计算机科学中用于解决各种子数组或子字符串问题的技术。滑动窗口技术通…

在 Mac 上恢复已删除的文件夹

“嗨&#xff0c;我刚刚运行了重复文件查找器应用程序 Gemini 来扫描我的 Mac 以清除重复文件。它找到了很多重复的文件和文件夹&#xff0c;只需单击一下&#xff0c;它就可以帮助我删除重复的文件/文件夹。但我认为它可能会删除一些有用的重复文件。我打开垃圾箱&#xff0c;…

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

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

AOP应用之系统操作日志

本文演示下如何使用AOP&#xff0c;去实现系统操作日志功能。 实现步骤 引入AOP包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.6</version></de…