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

阿里云可以做几个网站网络广告投放公司

阿里云可以做几个网站,网络广告投放公司,便民服务,做暧小视频免费视频在线观看网站一、智能指针简介 智能指针是一个类似于指针的类,将指针交给这个类对象进行管理,我们就可以像使用指针一样使用这个类,并且它会自动释放资源。 智能指针运用了 RAII 的思想(资源获得即初始化)。RAII 是指,用对象的生命周期来管理资…

一、智能指针简介

        智能指针是一个类似于指针的类,将指针交给这个类对象进行管理,我们就可以像使用指针一样使用这个类,并且它会自动释放资源。

        智能指针运用了 RAII 的思想(资源获得即初始化)。RAII 是指,用对象的生命周期来管理资源,类对象创建时拿到资源,析构时释放资源。

RAII 优点:

        1、不需要显式释放资源。

        2、在对象生命周期内,资源始终都是有效的。

简单的智能指针的示例:

template<class T>
class SmartPtr
{
public:SmartPtr(T* ptr):_ptr(ptr){}// 像指针一样使用,重载 * 和 ->T& operator*(){return *_ptr;}T* operator->(){return _ptr;}// 析构时释放资源~SmartPtr(){cout << "释放资源\n";if (_ptr)delete _ptr;}private:T* _ptr;
};

void func()
{int* p1 = new int[10];int* p2 = new int[10];int* p3 = new int[10];delete[] p1;delete[] p2;delete[] p3;
}

     在上述代码中,指针 p1, p2, p3 在创建时都有可能出现异常,如果在 p1 创建时出现异常,那么我们只需要捕获;如果在 p2 创建时出现异常,那么我们除了捕获异常,还需要释放 p1;而如果在 p3 创建时出现异常,那么我们又要释放 p1 和 p2。

        要写多个 try catch,这会让我们的代码变得十分复杂,并且可能会有遗漏,造成内存泄漏。

        这时,智能指针的优势就体现出来了,只需要把指针交给智能指针进行管理,就能够在生命周期结束时自动释放。

用上面的简单的智能指针示例

void func()
{SmartPtr<int> sp1(new int[10]);SmartPtr<int> sp2(new int[10]);SmartPtr<int> sp3(new int[10]);
}

        在对象的生命周期结束后,会自动调用析构释放资源。我们就不需要写复杂的代码,也不用担心内存泄漏的问题了。

二、智能指针的拷贝问题

        智能指针的拷贝如果不写的话,默认生成的是浅拷贝。而浅拷贝会使同一份资源释放两次,运行会报错。

void func()
{SmartPtr<int> sp1(new int[10]);SmartPtr<int> sp2(sp1);
}

这时候就有多种解决方案:

        1、auto_ptr

        将资源全部转给一方,将另一方置为空。(不靠谱,现在禁止使用了)

        2、unique_ptr

        拷贝有问题,干脆禁止拷贝。将拷贝封住,就可以了。(不需要拷贝的场景)

unique_ptr 的简单实现:

template<class T>
class Unique_Ptr
{
public:Unique_Ptr(T* ptr):_ptr(ptr){}// 像指针一样使用,重载 * 和 ->T& operator*(){return *_ptr;}T* operator->(){return _ptr;}// 析构时释放资源~Unique_Ptr(){cout << "释放资源\n";if (_ptr)delete _ptr;}Unique_Ptr(const Unique_Ptr<T>& up) = delete;Unique_Ptr<T>& operator=(const Unique_Ptr<T>& up) = delete;
private:T* _ptr;
};

3、shared_ptr

        通过引用计数解决多次析构问题

        用一个引用计数表示当前共有多少对象在使用该指针,每次析构都减引用计数,当引用计数减到0,就释放资源。

        为什么引用计数不能为 int 和 静态 static int ?

        int:如果引用计数是 int ,当我们改了一个引用计数,其他的对象无法同步。

        如:有三个对象 sp1, sp2, sp3,如果sp3拷贝sp2,无法告知sp1,sp1 无法同步引用计数。

        static int:如果用静态的,整个类共用一个引用计数,无法区分shared_ptr 管理的多个指针的引用计数。

        如:sp1(new int(1)); sp2(new int(2)); sp1 和 sp2 的引用计数肯定是不同的,但用静态无法区分,因为它是整个类共有的。

因此,引用计数用指针或引用最佳。

shared_ptr 简单实现代码

template<class T>
class Shared_Ptr
{
public:// 引用计数初始为 1Shared_Ptr(T* ptr):_ptr(ptr),_count(new int(1)){}// 像指针一样使用,重载 * 和 ->T& operator*(){return *_ptr;}T* operator->(){return _ptr;}// 返回引用计数int use_count(){return *_count;}Shared_Ptr(const Shared_Ptr<T>& sp){// 将资源拷贝过来,并 ++引用计数_ptr = sp._ptr;_count = sp._count;++(*_count);}Shared_Ptr<T>& operator=(const Shared_Ptr<T>& sp){// 防自己给自己赋值if (sp._ptr != _ptr){// 赋值会将原本的资源覆盖,因此要进行判断// 如果是最后一个对象,就析构释放,不是就 减减当前计数if (--(*_count) == 0){delete _ptr;delete _count;}// 拷贝资源,++拷贝的计数_ptr = sp._ptr;_count = sp._count;++(*_count);}return *this;}// 析构时释放资源~Shared_Ptr(){// 当引用计数减到 0,就释放资源if (--(*_count) == 0){cout << "释放资源\n";delete _ptr;delete _count;}else{// 打印调试cout << "减减引用计数,当前引用计数为: " << *_count << endl;}}
private:T* _ptr; // 指针int* _count; // 引用计数
};

        上述代码中存在线程安全问题,引用计数需要加锁保护!

多线程测试代码 测试记得把打印的调试信息注释掉

// 测试线程安全:拷贝 n 个对象
// 测试记得把打印的调试信息注释掉
void ThreadRoute(Shared_Ptr<int>& sp, int n, mutex& mtx)
{for (int i = 0; i < n; ++i){Shared_Ptr<int> test(sp);}
}void TestSharedThreadSafe()
{Shared_Ptr<int> sp(new int(1));mutex mtx;int n = 10000;// 因为不清楚内部实现,多线程的引用要使用库函数 refthread t1(ThreadRoute, ref(sp), n, ref(mtx));thread t2(ThreadRoute, ref(sp), n, ref(mtx));t1.join();t2.join();}

        多线程版 shared_ptr 实现,在修改引用计数时,加锁保护

// 多线程
template<class T>
class Shared_Ptr
{
public:// 引用计数初始为 1Shared_Ptr(T* ptr):_ptr(ptr), _count(new int(1)), _pmtx(new mutex){}// 像指针一样使用,重载 * 和 ->T& operator*(){return *_ptr;}T* operator->(){return _ptr;}void AddCount(){// 对公共资源 引用计数加加,加锁保护unique_lock<mutex> lock(*_pmtx);++(*_count);}void DelCount(){// 对公共资源 引用计数减减,加锁保护unique_lock<mutex> lock(*_pmtx);--(*_count);}// 返回管理的指针T* Get(){return _ptr;}// 返回引用计数 int use_count(){return *_count;}// 拷贝构造Shared_Ptr(const Shared_Ptr<T>& sp){// 将资源拷贝过来,并 ++引用计数_ptr = sp._ptr;_count = sp._count;_pmtx = sp._pmtx;// 将锁拿到后再 用锁保护,++引用计数AddCount();}Shared_Ptr<T>& operator=(const Shared_Ptr<T>& sp){// 防自己给自己赋值if (sp._ptr != _ptr){// 释放原本资源release();// 拷贝资源,++拷贝的计数_pmtx = sp._pmtx;_ptr = sp._ptr;_count = sp._count;AddCount();}return *this;}// 释放资源void release(){unique_lock<mutex> lock(*_pmtx);// 当引用计数减到 0,就释放资源if (--(*_count) == 0){// cout << "释放资源\n";// 释放锁之前 解锁lock.unlock();delete _ptr;delete _count;delete _pmtx;}else{// 打印调试// cout << "减减引用计数,当前引用计数为: " << *_count << endl;}}// 析构时释放资源~Shared_Ptr(){release();}
private:T* _ptr; // 指针int* _count; // 引用计数mutex* _pmtx; // 锁
};

三、shared_ptr 的循环引用问题

        当存在类里面有智能指针互相指向时,就会出现循环引用问题。

 

        因此,官方给 shared_ptr 配了一个小弟:weak_ptr

        weak_ptr 不是常规的智能指针,它具有以下特点

  • 它不支持 RAII

  • 支持像指针一样使用

  • 专门设计出来解决循环引用问题

        核心:weak_ptr 支持用 shared_ptr 构造,它不会加加引用计数。

        测试循环引用的代码:

struct ListNode
{// 双向链表Shared_Ptr<ListNode> _prev;Shared_Ptr<ListNode> _next;// 析构~ListNode(){cout << "释放节点\n";}
};void CirculaReferenceProblem()
{Shared_Ptr<ListNode> n1(new ListNode);Shared_Ptr<ListNode> n2(new ListNode);n1->_next = n2;n2->_prev = n1;
}

        weak_ptr 的简单实现

template<class T>
class Weak_Ptr
{
public:Weak_Ptr():_ptr(nullptr){}Weak_Ptr(const Shared_Ptr<T>& sp):_ptr(sp.Get()){}Weak_Ptr<T>& operator=(const Shared_Ptr<T>& sp){_ptr = sp.Get();return *this;}// 像指针一样使用,重载 * 和 ->T& operator*(){return *_ptr;}T* operator->(){return _ptr;}
private:T* _ptr;
};

        解决方案:在内部的互相引用处,用 weak_ptr 就可以了

struct ListNode
{// 在内部的互相引用处,用 weak_ptr 就可以了Weak_Ptr<ListNode> _prev;Weak_Ptr<ListNode> _next;~ListNode(){cout << "释放节点\n";}
};void CirculaReferenceProblem()
{Shared_Ptr<ListNode> n1(new ListNode);Shared_Ptr<ListNode> n2(new ListNode);n1->_next = n2;n2->_prev = n1;
}

四、定制删除器

        有的时候我们使用 new [] 开辟空间或传入的是文件指针,就可以定制删除器来指定使用 delete [] 或fclose() 删除。

        定制删除器就是传入一个可调用对象(仿函数或lambda或函数指针),在释放时调用。

        改变:

        1、成员加一个 function 包装的删除器,构造函数添加删除器模版

        2、release() 中删除改为用定制删除器删除

添加定制删除器

template<class T>
class Shared_Ptr
{
public:Shared_Ptr():_ptr(nullptr), _count(new int(1)), _pmtx(new mutex){}// 引用计数初始为 1Shared_Ptr(T* ptr):_ptr(ptr), _count(new int(1)), _pmtx(new mutex){}// 定制删除器template<class D>Shared_Ptr(T* ptr, D del):_ptr(ptr), _count(new int(1)), _pmtx(new mutex), _del(del){}// 像指针一样使用,重载 * 和 ->T& operator*(){return *_ptr;}T* operator->(){return _ptr;}void AddCount(){// 对公共资源 引用计数加加,加锁保护unique_lock<mutex> lock(*_pmtx);++(*_count);}void DelCount(){// 对公共资源 引用计数减减,加锁保护unique_lock<mutex> lock(*_pmtx);--(*_count);}// 返回管理的指针T* Get() const{return _ptr;}// 返回引用计数 int use_count(){return *_count;}// 拷贝构造Shared_Ptr(const Shared_Ptr<T>& sp){// 将资源拷贝过来,并 ++引用计数_ptr = sp._ptr;_count = sp._count;_pmtx = sp._pmtx;// 将锁拿到后再 用锁保护,++引用计数AddCount();}Shared_Ptr<T>& operator=(const Shared_Ptr<T>& sp){// 防自己给自己赋值if (sp._ptr != _ptr){// 释放原本资源release();// 拷贝资源,++拷贝的计数_pmtx = sp._pmtx;_ptr = sp._ptr;_count = sp._count;AddCount();}return *this;}// 释放资源void release(){unique_lock<mutex> lock(*_pmtx);// 当引用计数减到 0,就释放资源if (--(*_count) == 0){// cout << "释放资源\n";// 释放锁之前 解锁lock.unlock();// delete _ptr;// 改为用定制删除器删除_del(_ptr);delete _count;delete _pmtx;}else{// 打印调试// cout << "减减引用计数,当前引用计数为: " << *_count << endl;}}// 析构时释放资源~Shared_Ptr(){release();}
private:T* _ptr; // 指针int* _count; // 引用计数mutex* _pmtx; // 锁function<void(T*)> _del = [](T* ptr) {cout << "默认 delete\n";delete ptr;};
};

  测试代码

template<class T>
struct DeleteArr
{void operator()(T* ptr){cout << "delete[] ptr";delete[] ptr;}
};void TestDeletor()
{// 如果不传定制删除器,运行会报错Shared_Ptr<ListNode> sp(new ListNode[10], DeleteArr<ListNode>());
}

        到此结束,感谢大家观看♪(・ω・)ノ

http://www.hkea.cn/news/196207/

相关文章:

  • 蒙阴哪有做淘宝网站的钓鱼网站制作教程
  • 网站如何做导航条下拉菜单怎么做百度网页
  • 网站开发都做什么平台推广精准客源
  • 网站建设共享ip宁波seo搜索引擎优化
  • 学校网站建设必要性搜索引擎排名
  • 哪里有做区块链网站的百度网址大全在哪里找
  • 加盟平台网站怎么做竞价托管多少钱一个月
  • wordpress 微信 代码网站关键词怎么优化排名
  • 网站推广维护考研培训班哪个机构比较好
  • 网站后台生成器人工智能培训班收费标准
  • 在线做app的网站武汉网络营销公司排名
  • 了解深圳网站页面设计潍坊百度关键词优化
  • 制作网站怎样找公司来帮做seo词条
  • 网络销售有哪些站长工具seo排名
  • 做房产中介网站怎么注册一个自己的网站
  • 天津网站设计成功柚米全网推广成功再收费
  • 建设公司网站靠谱吗企业网站设计制作
  • 电子商务学什么课程内容兰州搜索引擎优化
  • 沧州网站建设制作设计优化能打开的a站
  • 石家庄网站建设推广报价怎么让百度快速收录网站
  • 建设局网站上开工日期选不了制作网站需要多少费用
  • 犬舍网站怎么做网页推广怎么做
  • 镇江核酸检测最新通知如何优化网页加载速度
  • wpf入可以做网站吗竞价托管外包费用
  • 公司设计网站需要包含什么资料优化排名软件
  • 日本樱花云服务器wan亚马逊seo关键词优化软件
  • layui框架的wordpress厦门站长优化工具
  • 微网站设计尺寸培训课程总结
  • 保险平台官网湖北搜索引擎优化
  • 西安微信小程序制作公司关键词优化方法