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

网站绑定别名好吗饮料网站建设

网站绑定别名好吗,饮料网站建设,中小型网站设计公司,代码网站模板目录 一. 为什么需要智能指针二.RAII和智能指针的设计思路三.C标准库智能指针的使用智能指针的构造删除器的使用 四.智能指针的原理unique_ptrshared_ptrweak_ptr循环引用的场景解决方法 五. 思考为什么shared_ptr和unique_ptr的构造需要explicit 一. 为什么需要智能指针 手动…

目录

  • 一. 为什么需要智能指针
  • 二.RAII和智能指针的设计思路
  • 三.C++标准库智能指针的使用
    • 智能指针的构造
    • 删除器的使用
  • 四.智能指针的原理
    • unique_ptr
    • shared_ptr
    • weak_ptr
      • 循环引用的场景
      • 解决方法
  • 五. 思考
    • 为什么shared_ptr和unique_ptr的构造需要explicit

一. 为什么需要智能指针

  1. 手动管理动态内存容易忘记 delete,导致内存泄漏。
  2. 不使用智能指针,在异常发生时可能导致 delete 未执行,从而引发内存泄漏
    可以参考下面这个例子
#include <iostream>
#include <stdexcept>void unsafeFunction() {int* raw_ptr = new int(100);  // 动态分配内存// 模拟一个可能抛出异常的操作if (true) {  // 假设这里条件触发异常throw std::runtime_error("Something went wrong!");}delete raw_ptr;  // 如果抛出异常,这句不会执行!std::cout << "Resource released (this won't print)\n";
}int main() {try {unsafeFunction();} catch (const std::exception& e) {std::cerr << "Caught exception: " << e.what() << "\n";}return 0;
}
//运行结果:Caught exception: Something went wrong!

二.RAII和智能指针的设计思路

  1. RALL是一种资源管理的类的设计思想,通过类的生命周期对获取到的资源进行管理,在类的生命周期内,资源保持有效,类的声明周期结束时,通过析构函数完成对资源的析构,以此防止内存泄漏。
  2. 智能指针是RAII设计思想的实现,智能指针还会通过重载operator->,operator*等操作符,来模仿指针的行为

三.C++标准库智能指针的使用

智能指针的构造

  1. unique_ptr,不支持拷贝,只支持移动,一份资源只能由一个对象管理
unique_ptr<Date> up1(new Date);// 不⽀持拷⻉
//unique_ptr<Date> up2(up1);   //错误做法// ⽀持移动,但是移动后up1也悬空,所以使⽤移动要谨慎
unique_ptr<Date> up3(move(up1));
  1. shared_ptr
    支持拷贝,也支持移动,底层用引用计数的方法实现,
shared_ptr<Date> sp1(new Date);// ⽀持拷⻉
shared_ptr<Date> sp2(sp1);// 
⽀持移动,但是移动后sp1也悬空,所以使⽤移动要谨慎 
shared_ptr<Date> sp4(move(sp1));
  1. weak_ptr
    不支持直接指向对象
    用来解决shared_ptr循环引用的问题,可以用shared_ptr初始化,具体在后面的原理讲
    在这里插入图片描述
  2. 上述这些智能指针也都可以使用std::make_…接口来进行创建对象,
unique_ptr<Date> up=std::make_unique<Date>;
shared_ptr<Date> sp=std::make_shared<Date>;

删除器的使用

智能指针在析构时默认使用delete析构,这也意味着如果不是new出来的资源,在析构时可能就会出错,标准库提供了传入删除器的接口,unique_ptr和shared_ptr的删除器实现不同,

  1. 因为new[]经常使⽤,所以unique_ptr和shared_ptr 实现了⼀个特化版本,这个特化版本析构时用的delete[]
unique_ptr<Date[]> up1(new Date[5]);shared_ptr<Date[]> sp1(new Date[5];
  1. unique_ptr在实例化模板阶段传入删除器,建议使用仿函数,函数指针,或者lambda表达式用decltype推到类型,仿函数最好实现
    在这里插入图片描述
template<class T>class DeleteArray{public:void operator()(T* ptr){delete[] ptr;}};//delete[]特化unique_ptr<Date[]> up1(new Date[5]);//仿函数unique_ptr<Date, DeleteArray<Date>> up2(new Date[5]);//函数指针
unique_ptr<Date, void(*)(Date*)> up3(new Date[5],DeleteArrayFunc<Date>)//lambad表达式
auto delArrOBJ = [](Date* ptr) {delete[] ptr; };unique_ptr<Date, decltype(delArrOBJ)> up4(new Date[5], delArrOBJ);
  1. shared_ptr在构造智能指针对象传入删除器,同样可以用上述三个方法,lambda最好实现
    在这里插入图片描述
    在这里插入图片描述
 //delete[]特化
shared_ptr<Date[]> sp1(new Date[5])//仿函数shared_ptr<Date> sp2(new Date[5], DeleteArray<Date>());//函数指针shared_ptr<Date> sp3(new Date[5], DeleteArrayFunc<Date>);//lambad表达式auto delArrOBJ = [](Date* ptr) {delete[] ptr; };shared_ptr<Date> sp4(new Date[5], delArrOBJ);

四.智能指针的原理

unique_ptr

基于一份资源只由一个智能指针对象管理的特性,
在底层实现时,要禁掉左值引用的复制拷贝和赋值操作

注意1:在实现右值引用的的赋值操作时,要先析构原来指向的对象
注意2:右值引用的赋值和拷贝操作都要让被操作指针的指向变成空

template<class T>
class unique_ptr
{
public:unique_ptr(T* ptr):_ptr(ptr){ }explicit unique_ptr(unique_ptr&& up):_ptr(up._ptr){up._ptr = nullptr;}unique_ptr(const unique_ptr& up) = delete;unique_ptr<T>& operator=(unique_ptr&& up){//先销毁原来的delete _ptr;_ptr = up._ptr;up._ptr = nullptr;return *this;}unique_ptr<T>& operator=(const unique_ptr& up)=delete;~unique_ptr(){delete _ptr;_ptr = nullptr;}T& operator*(){return *_ptr;}T* operator->(){if(_ptr!=nullptr)return _ptr;}private:T* _ptr = nullptr;
};

shared_ptr

支持拷贝,也支持移动,底层用引用计数的方法实现,
在一个对象直接构造时,在堆上申请一个空间,用来存储引用计数,拷贝和赋值操作时,引用计数就++,这样指向同一资源的智能指针用的就是同一个引用计数了

注意:赋值操作实现时,要先判断是否是自己给自己赋值,
还要判断原来指向的对象是否只有这一个智能指针,如果是,还要析构原来指向的资源

template <class T>
class shared_ptr
{
private:void release(){if (--(*_pcount)==0){_del(_ptr);delete _pcount;_ptr = nullptr;_pcount = nullptr;}}public:explicit  shared_ptr(T* ptr=nullptr):_ptr(ptr),_pcount(new int (1)){}template <class D>shared_ptr(T* ptr,D del):_ptr(ptr), _pcount(new int (1)),_del=del{}shared_ptr(shared_ptr& copy):_ptr = copy._pcount,_pcount = copy._pcount,_del = copy._del{(*_pcount)++;}shared_ptr<T>&  operator=(const shared_ptr& copy){if(_ptr != copy._ptr){//重要!!!//要先判断自己原来管理的资源需不需要释放release();_ptr = copy._pcount;_pcount = copy._pcount;_del = copy._del;*_pcount++;}return *this;}~shared_ptr(){release();}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get(){return _ptr;}int use_count(){return *_pcount;}
private:T* _ptr;int* _pcount;function<void(T*)> _del = [](T* ptr) {delete ptr; }
};

weak_ptr

循环引用的场景

在这里插入图片描述

n1析构了,引用记数变成1,n2析构了,引用记数变成1,
要想n1节点析构,引用计数要变成0,那就要n2析构
要想n2节点析构,引用计数要变成0,那就要n1析构
这样下来,哪个节点也析构不了,造成内存泄漏

解决方法

weak_ptr实现中,只是指向资源,但不增加引用计数,不承担析构资源的责任,这样一来,只要shared_ptr的引用计数变成0,就可以析构资源啦

注意:weak_ptr不支持直接绑定到资源,只支持直接绑定到shared_ptr

 struct ListNode{int _data;std::weak_ptr<ListNode> _next;std::weak_ptr<ListNode> _prev;};

底层简单实现

template <class T>
class weak_ptr
{
public://weak_ptr就是为了shared_ptr服务的,不提供直接构造weak_ptr(){}weak_ptr(const shared_ptr<T>& sp)_ptr(sp.get()){}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}private:T* _ptr=nullptr;};

五. 思考

为什么shared_ptr和unique_ptr的构造需要explicit

// 假设 shared_ptr 允许隐式转换(实际不允许!)
void useSharedPtr(std::shared_ptr<int> ptr) {// 使用 ptr
}int main() {int* raw_ptr = new int(42);useSharedPtr(raw_ptr);  // ❌ 如果允许隐式转换,会出问题!// 问题:raw_ptr 会被隐式转为 shared_ptr,但所有权不明确!// 可能导致 double-free(如果其他地方也接管了这个 raw_ptr)return 0;
}
  1. 对于上面这种情况,就可能重复delete导致出错

  2. 还有哪种情况也会出现所有权不明确的问题呢?

int* b = new int(42);
std::shared_ptr<int> sp1(b);
std::shared_ptr<int> sp2(b);  // 两个 shared_ptr 独立管理同一个 raw pointer

对于这种错误,可以通过std::make_shared规避,
如果只能用上述方法构造,要确保一个资源只初始化一个对象,这就需要程序员来控制了

http://www.dtcms.com/wzjs/596182.html

相关文章:

  • 企业网站设计能否以cms是什么材料
  • 企业网站有百度权重说明深圳市罗湖区住房和建设局网站
  • 网站建设项目前分析海南企业seo推广
  • 改图网站免费建站免费二级
  • 网站制作软件培训网站后台用户管理系统
  • 做个手机网站多少钱 广州网站数据库名称怎么改
  • 南昌哪个公司做网站好大学毕业网站设计代做
  • 上海中小网站建设茶叶网络推广方案
  • 简单网站开发实例汇总重庆网站建设网络推广
  • wordpress docx插件seo网站排名优化
  • 如何选择丹阳网站建设seo手机优化方法
  • 网站建设属于无形资产志愿服务网站开发
  • 宝山网站建设宝山广西建设人力资源网
  • 网站建设与维护项目六织梦网站背景
  • 建站之星安装教程wordpress文件存放不同目录下
  • 揭西网站建设自己做的网站能备案
  • 网站添加百度商桥wordpress添加网易云音乐
  • 个人怎么进行网站建设电商运营推广的方式和渠道有哪些
  • 网站制作里的更多怎么做千库网免费素材图库
  • 郑州上街区网站建设公司华夏名网网站管理助手
  • 城市建设的网站 政策法规设计专业招聘信息
  • 大庆工程建设公司网站跨境电商网站平台
  • 木樨园网站建设wordpress密码原理
  • 网站建设共享海南营业执照网上怎么申请
  • 深圳新型材料网站建设加盟创业
  • 普通网站备案wordpress 函数 应用
  • 株洲网站优化找哪家创建公司需要什么条件
  • 织梦 网站名称网站开发书籍推荐
  • 营销网站设计公司排名群辉nas 做网站
  • 青岛建设投资公司网站上海网站备案需要多久