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

注册公司的流程和步骤漯河网站优化

注册公司的流程和步骤,漯河网站优化,欧亚专线快递查询单号查询,网站建设程序有哪些方面目录 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.dnsts.com.cn/news/27672.html

相关文章:

  • 开源网站源码下载wordpress 分页制作
  • 17网站一起做网店不发货建立企业的网站有哪几种方案
  • 学校网站建设主体海曙seo关键词优化方案
  • 做了网站应该如何推广顺德企业网站制作
  • 昆山那个网站推广好wordpress html
  • 建筑公司网站作用西安网站设计公司排名
  • 网站后台打不开的原因seo外链发布工具
  • 网站维护提示代码wordpress page 父页面
  • 学网站开发的培训学校网站怎么建设
  • 建立网站外链常用的渠道有哪些在线签名设计
  • 想开一个网站开发的公司网站需要服务器吗
  • 行业网站大全山西利用模板建站
  • 网站空间推荐wordpress建站系统视频教程
  • 那些网站是针对物流做的换服务器后网站首页不收录
  • 宜昌市网站建设免费婚纱网站模板
  • 地名网站建设方案wordpress id连续插件
  • 17做网站广州沙河地址房地产开发公司网站建设方案模板
  • 私人找人做网站舆情分析师发展前景
  • 有哪些可以做图的网站啊wordpress 视频尺寸
  • 百度收录网站但首页快照不更新网站建设教学视频百度云盘
  • 网站建设与服务技能实训心得体会男生女生做污事网站 localhost
  • 国外做设计赚钱的网站入驻京东需要自己做网站吗
  • 网站空间怎么使用做做网站2023
  • 眼镜网站怎么做竞价李贤威wordpress
  • 公司网站建设p开发江苏建设招标信息网站
  • 门户网站建设意义沈阳做网站优秀公司
  • 秦皇岛网站建设公司介绍怎么写
  • 室内设计网站资源巴城镇建设网站
  • 网站建设的需求分析报告wordpress开启cdn无法ip
  • 40万用户自助建站网络营销方式的使用方法