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

广州网站设计有哪些专业邢台123生活贴吧

广州网站设计有哪些专业,邢台123生活贴吧,网页设计介绍说明,科技赋能千年残像目录 0. 前言 1. 懒汉式单例模式 1.1 最简单的单例模式 1.2 防止内存泄漏 1.2.1 智能指针的方法 1.2.2 静态嵌套的方法 1.3 保证线程安全 1.4 C11版本的优雅解决方案 2. 饿汉式单例模式 0. 前言 起因是在程序中重复声明了一个单例模式的变量#xff0c;后来程序怎么调…目录 0. 前言 1. 懒汉式单例模式 1.1 最简单的单例模式 1.2 防止内存泄漏 1.2.1 智能指针的方法 1.2.2 静态嵌套的方法 1.3 保证线程安全 1.4 C11版本的优雅解决方案 2. 饿汉式单例模式 0. 前言 起因是在程序中重复声明了一个单例模式的变量后来程序怎么调都不对最后发现变量是用单例模式修改是全局的所以决定好好梳理一下单例模式。 首先为什么要用单例模式就是因为我们希望一个类只有唯一一个实例并且提供一个全局的访问点。从这个描述不难看出这个实例应该是要static来修饰的。实际情况中比如我们想申请一个内存池程序都用这一块内存池那么就可以单例模式来实现。 1. 懒汉式单例模式 1.1 最简单的单例模式 先来看看最简单的单例模式怎么写然后分析一下有什么问题。 #include iostream using namespace std;// 最简单的单例模式 class Singleton{ public:// 获取实例的接口static Singleton* getInstance() {if (instance nullptr) {instance new Singleton(); // 使用new来创建一个新的实例对象} else {cout 重复创建返回已创建的实例。 endl;}return instance;} private:// 静态私有对象static Singleton* instance;// 构造函数一定要私有外部无法直接访问构造函数Singleton() {cout 运行构造函数 endl;};~Singleton() {cout 运行析构函数 endl;}; }; // 要在类外进行初始化 Singleton* Singleton::instance nullptr;int main(){Singleton* s1 Singleton::getInstance();Singleton* s2 Singleton::getInstance();return 0; }这里有两个点需要特别的注意 单例模式的类需要有一个静态私有的对象是这个类的实例且必须在类外进行初始化。获取实例的接口getInstance()函数式可以被访问和调用的但是必须返回static类型的变量实际上就是返回这个类的唯一实例。补充下析构函数私有化的原因保证只能在堆上new一个新的类对象。因为C是一个静态绑定的语言。在编译过程中所有的非虚函数调用都必须分析完成即使是虚函数也需检查可访问性。当在栈上生成对象时对象会自动析构也就说析构函数必须可以访问。而堆上生成对象由于析构时机由程序员控制所以不一定需要析构函数。 按照上面的写法基本上满足了单例模式的初衷要一个只有一个实例的类。但是存在两个问题一个是因为使用到了new进行创建就需要人为进行delete的释放操作否则就会造成内存泄漏。第二个是程序乍一看只会创建一块内存空间但是如果考虑多线程那么就有可能多个线程分别创建了多块内存空间的实例与我们设计单例模式的初衷相违背。 1.2 防止内存泄漏 1.2.1 智能指针的方法 运行1.1的程序结果为 运行构造函数 重复创建返回已创建的实例。 可以发现并没有调用析构函数。这里补充一下析构函数的作用释放对象的使用资源并销毁对象的非static数据成员。而我们定义的instance成员变量static的所以无法直接使用析构函数进行释放。虽然事例的简单程序在运行完之后static变量会自动释放但是在很多复杂的程序中使用完instance却不释放是非常致命的会导致内存泄漏的问题。这里采用智能指针的方法并借用智能指针的reset函数定义一个销毁的成员函数通过这个成员函数调用delete来释放我们创建的new内存达到析构的目的。看看下面的实现。 #include iostream #include memory using namespace std;class Singleton{ public:// 公有接口获取唯一实例static shared_ptrSingleton getInstance() {if (instance nullptr) {instance.reset(new Singleton(), destoryInstance);}else {cout 重复创建返回异创建的实例。 endl;}return instance;}// 定义销毁的实例static void destoryInstance(Singleton* x) {cout 自定义释放实例 endl;delete x;} private:Singleton() {cout 运行构造函数。 endl;};~Singleton() {cout 运行析构函数。 endl;}; private:// 静态私有对象static shared_ptrSingleton instance; };// 初始化 shared_ptrSingleton Singleton::instance;int main(){shared_ptrSingleton s1 Singleton::getInstance();shared_ptrSingleton s2 Singleton::getInstance();return 0; } 运行结果为 运行构造函数。 重复创建返回异创建的实例。 自定义释放实例 运行析构函数。 可以看到我们通过智能指针在使用完instance资源后调用了自定义的释放函数即delete了new出来的空间达到了运行析构函数的目的防止了内存泄漏。 1.2.2 静态嵌套的方法 解决内存的泄漏的方法总之是要把释放的过程先写好不能靠用户每次自己释放。对于本次分享的例子就是要把delete放进代码里。除了利用智能指针的释放函数来调用delete之外也可以显式的调用delete函数要单独嵌套一个类把这个delete函数放进嵌套类的公有析构函数中。实现过程如下 #include iostream using namespace std; class Singleton{ public:// 公有接口获取唯一实例static Singleton* getInstance() {if (instance nullptr) {if (instance nullptr) {instance new Singleton();}}else {cout 重复创建返回已创建的实例。 endl;}return instance;} private:Singleton() {cout 运行构造函数。 endl;};~Singleton() {cout 运行析构函数。 endl;};// 定义一个删除器class Deleter {public:Deleter() {};~Deleter() {if (instance ! nullptr) {cout 删除器启动。 endl;delete instance;instance nullptr;}}};static Deleter deleter; // 删除器也是静态成员变量 private:// 静态私有对象static Singleton* instance; };// 初始化 Singleton* Singleton::instance nullptr; Singleton::Deleter Singleton::deleter;int main() {Singleton* s1 Singleton::getInstance();Singleton* s2 Singleton::getInstance();return 0; } 运行结果为 运行构造函数。 重复创建返回已创建的实例。 删除器启动。 运行析构函数。 1.3 保证线程安全 首先修改一下1.1中的程序主要是增加一些打印然后用多个线程创建Singleton的实例看看是否每个线程都是访问的同一个内存地址。 #include iostream #include thread using namespace std;class Singleton{ public:// 获取实例的接口static Singleton* getInstance() {if (instance nullptr) {instance new Singleton(); // 使用new来创建一个新的实例对象cout 创建地址为: instance endl;} else {cout 重复创建返回已创建的实例。 endl;}return instance;} private:// 静态私有对象static Singleton* instance;// 构造函数一定要私有外部无法直接访问构造函数Singleton() {cout 运行构造函数 endl;};~Singleton() {cout 运行析构函数 endl;}; }; // 要在类外进行初始化 Singleton* Singleton::instance nullptr;int main(){// Singleton* s1 Singleton::getInstance();// Singleton* s2 Singleton::getInstance();thread t1([] {Singleton* s1 Singleton::getInstance();});thread t2([] {Singleton* s2 Singleton::getInstance();});t1.join();t2.join();return 0; }运行结果如下 运行构造函数 创建地址为:0x7f0988000b60 运行构造函数 创建地址为:0x7f0980000b60 可以发现两个线程分别new出了一段内存空间有一定几率是同一段会报重复创建。显然这违背了我们单例模式的初衷。 解决方法是进行加锁让一个线程先执行完另一个线程才能获得new的权限。代码如下 #include iostream #include mutex #include thread using namespace std;class Singleton{ public:static Singleton* getInstance() {if (instance nullptr) {lock_guardmutex l(mutex1); // 加锁保证线程安全if (instance nullptr) {instance new Singleton();cout 创建地址为: instance endl;}}else {cout 重复创建返回已创建的实例。 endl;}return instance;} private:static mutex mutex1;// 锁static Singleton* instance;Singleton() {cout 运行构造函数 endl;};~Singleton() {cout 运行析构函数 endl;}; };// 初始化 Singleton* Singleton::instance nullptr; mutex Singleton::mutex1;int main(){thread t1([](){Singleton* s1 Singleton::getInstance();});thread t2([](){Singleton* s2 Singleton::getInstance();});t1.join();t2.join();return 0; }运行结果为 运行构造函数 创建地址为:0x7f90d4000b60 重复创建返回已创建的实例。 加锁后即使是多个线程也只会申请一块内存空间。 1.4 C11版本的优雅解决方案 上面只是为了将这个问题表述清楚在C11中static变量是可以保证线程安全的同时直接用static变量而不用new就可以获得线程安全的且无内存泄漏的优雅写法如下 #include iostream #include thread using namespace std; class Singleton{ public:// 公有接口获取唯一实例static Singleton* getInstance() {static Singleton instance;cout 地址为: instance endl;return instance;}private:Singleton() {cout 运行构造函数 endl;};~Singleton() {cout 运行析构函数 endl;}; };int main() {thread t1([] {Singleton* s1 Singleton::getInstance();});thread t2([] {Singleton* s2 Singleton::getInstance();});t1.join();t2.join();return 0; } 运行结果如下 运行构造函数 地址为:0x55b7df269152 地址为:0x55b7df269152 运行析构函数 可以看到访问的内存地址一样析构函数也正常的运行了。 2. 饿汉式单例模式 饿汉式和懒汉式的差别是饿汉式提前进行了创建而如果提前创建static变量那么在程序开始前这个变量就创建好了因此不存在线程不安全的问题只需要保证不内存泄漏即可。用智能指针的方式实现代码如下 #include iostream #include thread using namespace std; class Singleton{ public:// 公有接口获取唯一实例static shared_ptrSingleton getInstance() {cout 地址为: instance endl;return instance;}// 定义销毁的实例static void destoryInstance(Singleton* x) {cout 自定义释放实例 endl;delete x;}private:Singleton() {cout 运行构造函数 endl;};~Singleton() {cout 运行析构函数 endl;}; private:// 静态私有对象static shared_ptrSingleton instance; };// 初始化 shared_ptrSingleton Singleton::instance(new Singleton(), destoryInstance);int main(){thread t1([] {shared_ptrSingleton s1 Singleton::getInstance();});thread t2([] {shared_ptrSingleton s2 Singleton::getInstance();});t1.join();t2.join();return 0; } 运行结果为 运行构造函数。 地址为:0x55977895ceb0 地址为:0x55977895ceb0 自定义释放实例 运行析构函数。 也可以考虑优雅的写法 #include iostream #include thread using namespace std; class Singleton{ public:// 公有接口获取唯一实例static Singleton* getInstance() {static Singleton instance;cout 地址为: instance endl;return instance;}private:// 私有构造函数Singleton() {cout 运行构造函数。 endl;};// 私有析构函数~Singleton() {cout 运行析构函数。 endl;}; };int main(){thread t1([] {Singleton* s1 Singleton::getInstance();});thread t2([] {Singleton* s2 Singleton::getInstance();});t1.join();t2.join();return 0; } 输出的结果为 运行构造函数。 地址为:0x55aa7a895152 地址为:0x55aa7a895152 运行析构函数。
http://www.hkea.cn/news/14365065/

相关文章:

  • 网站建设有什么技术免费分销平台有哪些
  • 全网营销推广网站建设大连建设局网站地址
  • 湘潭网站制作建设WordPress入门编辑器
  • 京东网站建设分析高并发网站建设
  • 永康市网站建设制作WordPress文章中的编辑去掉
  • 北京海淀网站建设学做网站开发
  • 南昌好的做网站的公司北京网站改版哪家好
  • 网站 专题建设服务wordpress怎么做淘客网站
  • 自己电脑做的网站如何映射到公网成都专业做网站
  • 惠州哪家做网站好建立营销网络
  • 百度网站是百度公司做的吗网络营销方式有哪些分类
  • 做常识的网站怎么做二维码链接网页
  • it公司怎么在国外网站做宣传最新热门事件
  • jsp开发网站开发源码合肥建设管理学校网站首页
  • 网站开发工程师证太原网站建设找山西云起时
  • 网站推广销售腾讯会员被告怎么办小程序一般用什么语言开发
  • 新闻类网站建设深圳网站开发公司哪家好
  • 兼职做效果图的网站私人影吧服务器
  • 开发网站公司价格黄页广告网站
  • 网站到底备案好不好六安人论坛
  • 建设本地网站 配置iis创意设计ppt
  • 菜鸟必读 网站被入侵后需做的检测 1湖南网站seo营销多少费用
  • 鲤城网站建设推广服务公司搜索引擎优化seo的策略主要有
  • 中国空间站完整图临沂国际外贸网站建设
  • 上海建设项目中标公示网站网站建设和托管哪家好
  • 接单网站设计 只做设计图报价画册设计理念和设计思路
  • 网站建设整体方案论文工业品牌设计公司
  • dedecms网站地图插件非标自动化外包平台
  • 龙岗网站建设流程重庆新闻频道回放观看
  • 为该网站做自适应江西企业网站建设哪家好