当前位置: 首页 > news >正文

400电话安装佛山营销网站建设搜索引擎优化作业

400电话安装佛山营销网站建设,搜索引擎优化作业,洛阳电商网站建设公司排名,广州天河区做网站的公司文章目录 简介源码解析1. 引用计数的实现方式2. deleter静态方法的赋值时间节点3.make_smart的实现方式 与 好处4. 几种构造函数4.1 空构造函数4.2 接收指针的构造函数4.3 接收指针和删除方法的构造函数 , 以及auto进行模板lambda的编写4.4 拷贝构造函数4.5 赋值运算符 5. rele…

文章目录

    • 简介
    • 源码
    • 解析
      • 1. 引用计数的实现方式
      • 2. deleter静态方法的赋值时间节点
      • 3.make_smart的实现方式 与 好处
      • 4. 几种构造函数
        • 4.1 空构造函数
        • 4.2 接收指针的构造函数
        • 4.3 接收指针和删除方法的构造函数 , 以及auto进行模板lambda的编写
        • 4.4 拷贝构造函数
        • 4.5 赋值运算符
      • 5. release函数, 指针的delete 和 设置为nullptr
      • 6. 获取内部变量, 指针和引用

简介

  • git地址: shimachao/smart_ptr
  • 说明: 这是一个仿写shared_ptr的库, 只有简短的200行, 实现了shared_ptr的大部分功能, 上手简单, 非常适合新手阅读.
  • 本文说明: 由于本项目没有那么多难点, 就不再像上篇开源代码阅读中c++源码阅读__ThreadPool__正文阅读一样, 不单独开一个前提知识部分了, 由于本项目比较简单, 大家就当作对shared_ptr的一次复习. 看一乐呵就行.

源码

此代码在c++20环境下直接可以运行, 源码如下

#pragma once#include <functional>// 模仿shared_ptr实现一个智能指针
template <typename T>
class smart_ptr
{
public:smart_ptr();explicit smart_ptr(T*);smart_ptr(const smart_ptr&);smart_ptr(T*, std::function<void(T*)>);smart_ptr& operator=(const smart_ptr&);T& operator*() const;T* operator->() const;~smart_ptr();// 向bool的类型转换explicit operator bool() const;bool unique();void reset();void reset(T*);void reset(T*, std::function<void(T*)>);T* release();T* get() const;private:// 默认的deleterstatic std::function<void(T*)> default_del;private:unsigned* m_p_use_count = nullptr;T* m_pobject = nullptr;std::function<void(T*)> m_del = default_del;
};template <typename T>
std::function<void(T*)> smart_ptr<T>::default_del = [](T*p) {delete p; p = nullptr; };template <typename T, typename... Args>
smart_ptr<T> make_smart(Args&&... args)
{smart_ptr<T> sp(new T(std::forward<Args>(args)...));return sp;
}template <typename T>
smart_ptr<T>::smart_ptr():m_pobject(nullptr), m_p_use_count(new unsigned(1))
{
}template <typename T>
smart_ptr<T>::smart_ptr(T *p):m_pobject(p), m_p_use_count(new unsigned(1))
{
}template <typename T>
smart_ptr<T>::smart_ptr(T *p, std::function<void(T*)> del):m_pobject(p), m_p_use_count(new unsigned(1)), m_del(del)
{
}template <typename T>
smart_ptr<T>::smart_ptr(const smart_ptr& rhs):m_pobject(rhs.m_pobject), m_p_use_count(rhs.m_p_use_count), m_del(rhs.m_del)
{(*m_p_use_count)++;
}template <typename T>
smart_ptr<T>& smart_ptr<T>::operator =(const smart_ptr &rhs)
{// 使用rhs的deleterm_del = rhs.m_del;// 递增右侧运算对象的引用计数++(*rhs.m_p_use_count);// 递减本对象的引用计数if (--(*m_p_use_count) == 0){// 如果管理的对象没有其他用户了,则释放对象分配的成员m_del(m_pobject);delete m_p_use_count;}m_p_use_count = rhs.m_p_use_count;m_pobject = rhs.m_pobject;return *this; // 返回本对象
}template <typename T>
T& smart_ptr<T>::operator*() const
{return *m_pobject;
}template <typename T>
T* smart_ptr<T>::operator->() const
{return &this->operator*();
}template <typename T>
smart_ptr<T>::~smart_ptr()
{if (--(*m_p_use_count) == 0){m_del(m_pobject);m_pobject = nullptr;delete m_p_use_count;m_p_use_count = nullptr;}
}template <typename T>
bool smart_ptr<T>::unique()
{return *m_p_use_count == 1;
}template <typename T>
void smart_ptr<T>::reset()
{(*m_p_use_count)--;if (*m_p_use_count == 0){m_del(m_pobject);}m_pobject = nullptr;*m_p_use_count = 1;m_del = default_del;
}template <typename T>
void smart_ptr<T>::reset(T* p)
{(*m_p_use_count)--;if (*m_p_use_count == 0){m_del(m_pobject);}m_pobject = p;*m_p_use_count = 1;m_del = default_del;
}template <typename T>
void smart_ptr<T>::reset(T *p, std::function<void(T*)> del)
{reset(p);m_del = del;
}template <typename T>
T* smart_ptr<T>::release()
{(*m_p_use_count)--;if (*m_p_use_count == 0){*m_p_use_count = 1;}auto p = m_pobject;m_pobject = nullptr;return p;
}template <typename T>
T* smart_ptr<T>::get() const
{return m_pobject;
}template <typename T>
smart_ptr<T>::operator bool() const
{return m_pobject != nullptr;
}

解析

这里会把smart_ptr类中每一部分都单独拿出来说明, 并进行举例

1. 引用计数的实现方式

我们可以看到他的实现方式

unsigned* m_p_use_count = nullptr;

使用的是整数的指针, 如果不使用指针的话, 那么是打不到公用引用计数的效果的, 如下

int* a1 = new int(1);
int* a2 = a1;
*a2 += 1;
cout << *a1 << endl;
cout << *a2 << endl;int a3 = 1;
int a4 = a3;
a3 += 1;
cout << a4 << endl;
cout << a4 << endl;int a5 = 1;
int& a6 = a5;
a5++;
cout << a5 << endl;
cout << a6 << endl;

执行结果
在这里插入图片描述
那么我们是不是也可以用引用&来实现引用计数的共用呢? 我觉得是可以的

2. deleter静态方法的赋值时间节点

template <typename T>
class smart_ptr
{
private:// 默认的deleterstatic std::function<void(T*)> default_del;std::function<void(T*)> m_del = default_del;
}
template <typename T>
std::function<void(T*)> smart_ptr<T>::default_del = [](T*p) {delete p; p = nullptr; };

静态方法的赋值, 是 程序启动并进入主函数之前进行赋值的, 具体地这个初始化是在包含这行代码的翻译单元被加载时完成的, 所以 default_del在任何smart_ptr的构造函数调用之前就赋值了.
m_del的赋值是在smart_ptr的构造函数被调用时赋值的

3.make_smart的实现方式 与 好处

template <typename T, typename... Args>
smart_ptr<T> make_smart(Args&&... args)
{smart_ptr<T> sp(new T(std::forward<Args>(args)...));return sp;
}

这里右值引用完美转发相关的知识在左值右值, 左值引用右值引用,完美转发这篇博客中有详细介绍.
这里和shared_ptr一样, 也是接收目标类的构造函数的参数, 直接返回智能指针的实现方式
好处: 我们使用make_smart的方式, 创建智能指针非常好, 因为不用我们手动new一个指针出来, 那么智能指针外部就没有该指针的变量, 就不会造成一些未知错误, 保证了在指针的生命周期内, 都是被智能指针安全管理的.

4. 几种构造函数

常用的构造函数和赋值运算符 在这篇文章里有介绍
C++基础知识,对象移动,拷贝构造函数,移动拷贝构造函数,赋值运算符,移动赋值运算符

4.1 空构造函数
template <typename T>
smart_ptr<T>::smart_ptr():m_pobject(nullptr), m_p_use_count(new unsigned(1))
{}

这个方法是构造一个内容为空的智能指针, 声明方式如下
smart_prt<MyClass> sp();
这个可以配合后面的reset方法使用, 给智能指针重新赋值

4.2 接收指针的构造函数
template <typename T>
smart_ptr<T>::smart_ptr(T *p):m_pobject(p), m_p_use_count(new unsigned(1))
{}

使用方式如下, 但是不推荐这种方式, 因为外部有了指针变量s1, 这就给智能指针的管理带来了未知的风险

MyStruct* s1 = new MyStruct(1, 2);
smart_ptr<MyStruct> sp(s1);
4.3 接收指针和删除方法的构造函数 , 以及auto进行模板lambda的编写
template <typename T>
smart_ptr<T>::smart_ptr(T *p, std::function<void(T*)> del):m_pobject(p), m_p_use_count(new unsigned(1)), m_del(del)
{}

这个构造方法就是上面4.2多加一个参数, 没什么好说的, 但是其中delete方法的传入, 我们可以通过auto来编写模板lambda, 这是c++新的特性, 如下

auto deleter = [](auto* p) {delete *p; p = nullptr;};
MyStruct* s = new MyStruct(1, 2);
smart_ptr<MyStruct> sp(s, deleter);

这样, 我们就不用template写一大堆, 而直接构造出了一个模板函数

4.4 拷贝构造函数

拷贝构造函数, 会造成引用计数+1, 两个智能指针指向的是同一块地址

template <typename T>
smart_ptr<T>::smart_ptr(const smart_ptr& rhs) :m_pobject(rhs.m_pobject), m_p_use_count(rhs.m_p_use_count), m_del(rhs.m_del)
{(*m_p_use_count)++;
}

=符号的赋值, 是赋值的内容, 不是变量本身的地址设置为一致(这是引用的=), 所以指针的=, 是指针变量内指向的地址设置为相同

MyStruct* s1 = new MyStruct(1, 2);
smart_ptr<MyStruct> sp(s1);
smart_ptr<MyStruct> sp2(sp);
cout << std::boolalpha;
cout << (sp.get() == sp2.get()) << endl;

执行结果
在这里插入图片描述

4.5 赋值运算符

赋值运算符 和 拷贝构造函数就大不一样了, 赋值运算符会把等号左边的智能指针内的变量引用计数-1, 如果引用计数为0了, 还会释放资源

template <typename T>
smart_ptr<T>& smart_ptr<T>::operator =(const smart_ptr &rhs)
{// 使用rhs的deleterm_del = rhs.m_del;// 递增右侧运算对象的引用计数++(*rhs.m_p_use_count);// 递减本对象的引用计数if (--(*m_p_use_count) == 0){// 如果管理的对象没有其他用户了,则释放对象分配的成员m_del(m_pobject);delete m_p_use_count;}m_p_use_count = rhs.m_p_use_count;m_pobject = rhs.m_pobject;return *this; // 返回本对象
}

所以根据代码, 我们合理预测, 如果=左边的智能指针引用计数如果是1的话, 那么使用了赋值运算符, 就会造成内部的指针析构
测试代码

struct MyStruct
{MyStruct() = default;MyStruct(int a, int b) :a(a), b(b) {}~MyStruct() { cout << "~MyStruct ("  << a << "," << b << ")" << endl;}int a;int b;
};int main()
{smart_ptr<MyStruct> sp1 = make_smart<MyStruct>(1, 2);smart_ptr<MyStruct> sp2 = make_smart<MyStruct>(3, 4);sp1 = sp2;cout << "==========" << endl;return 0;
}

执行结果
在这里插入图片描述

可以看到, 是sp1在程序结束之前析构的

5. release函数, 指针的delete 和 设置为nullptr

这里我们要明确,delete是把指针指向的内容进行析构, 而直接把指针设置为nullptr, 只是把当前这个指针变量设置为nullptr, 对于指针指向的内容, 不做任何处理
比如release函数

template <typename T>
T* smart_ptr<T>::release()
{(*m_p_use_count)--;if (*m_p_use_count == 0){*m_p_use_count = 1;}auto p = m_pobject;m_pobject = nullptr;return p;
}

在这个函数里, 只是把m_pojbect这个指针变量本身设置为了nullptr, 而指针指向的变量没有做任何操作, 最后把这个指针变量copy一份, 返回出去了
测试代码

struct MyStruct
{MyStruct() = default;MyStruct(int a, int b) :a(a), b(b) {}~MyStruct() { cout << "~MyStruct ("  << a << "," << b << ")" << endl;}int a;int b;
};int main()
{smart_ptr<MyStruct> sp1 = make_smart<MyStruct>(1, 2);MyStruct* s1 = sp1.release();cout << "=========" << endl;delete s1;return 0;
}

执行结果 可以看到, release确实没有造成析构
在这里插入图片描述

6. 获取内部变量, 指针和引用

有两个方法, 一个是重载的操作符*, 一个是get方法
只不过get获取的指针
*获取的是引用

template <typename T>
T& smart_ptr<T>::operator*() const
{return *m_pobject;
}
template <typename T>
T* smart_ptr<T>::get() const
{return m_pobject;
}

测试代码

int main()
{smart_ptr<MyStruct> sp1 = make_smart<MyStruct>(1, 2);cout << std::boolalpha << endl;// (*sp1)获取了引用: &MyStruct, 转为指针 *(&MyStruct)cout << (&(*sp1) == sp1.get()) << endl;return 0;
}

执行结果
在这里插入图片描述

http://www.15wanjia.com/news/46563.html

相关文章:

  • 做国外搞笑网站有哪些新闻稿撰写
  • 游戏网站建设一条龙志鸿优化设计电子版
  • 如何建设和优化一个网站谷歌怎么投放广告
  • wordpress 文章统计it菜鸡网seo
  • 做原创音乐的网站今日头条站长平台
  • 做电子商务平台网站网站推广的方法有哪几种
  • 重庆上网app百度爱采购优化排名软件
  • 做外汇需要了解的网站企业网络营销青岛
  • 音乐主题wordpress提升网页优化排名
  • 做我的奴隶腾讯网站快速排名网站
  • 深圳福田疫情最新情况武汉seo创造者
  • 株洲网站做的好的公司推广信息怎么写
  • 微信网站制作企业微信小程序开发一个多少钱啊
  • 东阳做网站的公司青岛seo整站优化招商电话
  • 东莞 建网站重庆seo推广服务
  • 龙岗网站建设价格百度官方营销推广平台加载中
  • 厦门方易网站制作有限公司创建网站的软件
  • 网站地图提交给百度淘宝seo培训
  • 如何把旅行社网站做的好看全国新冠疫苗接种率
  • 毕业设计代做的网站靠谱吗临沂网站seo
  • 东莞市住房建设网站搜索引擎竞价推广的优势
  • 深圳单位网站建设服务公司推广方案应该有哪些方面
  • 免费做网站建设最佳磁力引擎吧
  • 智能网站建设软件seo教学实体培训班
  • 政府网站建设包括什么域名注册信息怎么查
  • 泉州做网站公司理发培训专业学校
  • 做影视网站规模不大上海免费关键词排名优化
  • 嘉定网站建设哪家便宜灰色关键词排名代发
  • 广州室内设计培训学校市场seo是什么意思
  • 滁州网站定制长尾关键词挖掘爱站网