首页 > 编程语言 >C++11 标准库头文件模拟实现

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

时间:2024-06-23 18:58:42浏览次数:3  
标签:11 SharedPtr 头文件 C++ values const ref ptr size

系列文章目录


文章目录


前言

暂不考虑支持多线程
常用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


总结

标签:11,SharedPtr,头文件,C++,values,const,ref,ptr,size
From: https://blog.csdn.net/surfaceyan/article/details/139887490

相关文章

  • P5311 [Ynoi2011] 成都七中
    题目描述给你一棵\(n\)个节点的树,每个节点有一种颜色,有\(m\)次查询操作。查询操作给定参数\(l\r\x\),需输出:将树中编号在\([l,r]\)内的所有节点保留,\(x\)所在连通块中颜色种类数。每次查询操作独立。对于\(100\%\)的数据,所有出现过的数在\([1,10^5]\)之间,保证每......
  • Oracle 11gR2 RAC 集群服务启动与关闭总结
      关闭过程(CRS集群关闭->关闭数据库)1.关闭数据库:用oracl用户执行srvctl命令语法:srvctlstopdatabase-ddbname[-oimmediate]作用:可以一次性关闭dbname的所有实例[oracle@rac1 ~]$ srvctl stop database -d racdb  -停止所有节点上的实例然后查看状态:[oracle@ra......
  • Python编程技巧:下划线的11种妙用,看看你知道几种?
    文章目录......
  • P1199 NOIP2010 普及组 三国游戏
    P1199NOIP2010普及组三国游戏P1199[NOIP2010普及组]三国游戏-洛谷|计算机科学教育新生态(luogu.com.cn)这题虽然是有博弈论的标签,但是完全没必要,直接贪心即可。下面一个武将的最大默契值称为第一默契值,次大为第二,以此类推。如何最大默契值根据题意,通过观察规律,你......
  • CAN收发器TJA1145A休眠唤醒应用
    目录1.  TJA1145 工作原理简介2. SPI通讯3. 唤醒源配置4. 休眠配置    1.  TJA1145 工作原理简介    TJA1145的唤醒工作原理主要依赖于其内部的唤醒机制和外部硬件的配合,主要涉及低功耗状态、选择性唤醒功能。TJA1145是一款CAN收发器,它支持......
  • 【异常错误】so.11: undefined symbol: cublasLtHSHMatmulAlgoInit, version libcubla
    今天安装了一个新的conda环境,但是一开始运行就出现错误: Traceback(mostrecentcalllast): File"/home/mapengsen/anaconda3/envs/37/lib/python3.7/site-packages/torch/__init__.py",line172,in_load_global_deps  ctypes.CDLL(lib_path,mode=ctypes.RTLD......
  • C++题解(1) 信息学奥赛一本通 1003:对齐输出 洛谷 B2004:对齐输出 土豆编程 T1003:对
    【题目描述】读入三个整数,按每个整数占8个字符的宽度,右对齐输出它们,按照格式要求依次输出三个整数,之间以一个空格分开。【输入】只有一行,包含三个整数,整数之间以一个空格分开。【输出】只有一行,按照格式要求依次输出三个整数,之间以一个空格分开。【输入样例】......
  • C++中的八大设计原则
    目录摘要C+中的8大设计原则1.单一职责原则(SingleResponsibilityPrinciple,SRP)2.开放封闭原则(Open/ClosedPrinciple,OCP)3.里氏替换原则(LiskovSubstitutionPrinciple,LSP)4.依赖倒置原则(DependencyInversionPrinciple,DIP)5.接口隔离原则(Inte......
  • C++U7-10-最小生成树
    本节课作业讲解视频:链接:https://pan.baidu.com/s/1lLlmhShdat9HuJWx7Rp_tA?pwd=0000提取码:0000  最小生成树是一种在无向图中寻找特定结构的算法结果,它具有多种实际应用。以下是关于最小生成树的一些主要应用:网络布局问题:在一个连通加权无向图中,最小生成树算法可以帮......
  • C++面向对象多级菜单向Arduino的移植
    前段时间写了一篇文章《C++面向对象语言自制多级菜单》,文中指出了可以将HeleMenu库进行移植,现已完成技术思路,特此记录。一、特性基本与上一篇文章指出的一致,只是将菜单显示和响应函数合二为一二、代码实现基本与上一篇文章指出的一致,只是考虑到右值和左值的问题,将形参改为了co......