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

购物网站开发意义泰州网络科技有限公司

购物网站开发意义,泰州网络科技有限公司,中和seo公司,白银网站建设熊掌号单例九品--第五品 上一品引入写在前边代码部分1代码部分2实现方式评注与思考下一品的设计思考 上一品引入 第四品中可能会因为翻译单元的链接先后顺序#xff0c;造成静态初始化灾难的问题。造成的原因是因为存在调用单例对象前没有完成定义的问题#xff0c;这一品将着重解… 单例九品--第五品 上一品引入写在前边代码部分1代码部分2实现方式评注与思考下一品的设计思考 上一品引入 第四品中可能会因为翻译单元的链接先后顺序造成静态初始化灾难的问题。造成的原因是因为存在调用单例对象前没有完成定义的问题这一品将着重解决这个问题。 写在前边 基本思路 • 引入初始化类 • 初始化类是单例类的子类可以访问单例类的所有成员 • 通过初始化类的实例作为纽带一定程度上控制初始化顺序优点 • 初始化类可以精确控制初始化时机缺点 • 似乎可以解决 static initialization order fiasco 问题但实际上程序包含了更深层次的 隐患:可能出现未定义的行为 代码部分1 三个文件: main.cpp sing.cpp和sing.h main.cpp #include sing.hstatic Sing::Init init; auto singletonInst2 singletonInst-val;int main(int argc, char** argv) {std::cout get value: singletonInst2 \n; }sing.cpp #include sing.h #include memory #include iostreamstd::unique_ptrSing singletonInst;Sing::Init::Init() {if (!singletonInst){singletonInst.reset(new Sing()); } }sing.h #pragma once #include iostream #include memoryclass Sing { public:struct Init{Init();Init(const Init) delete;Init operator (const Init) delete;};public:~Sing(){std::cout Sing destroy\n;}private:Sing(){std::cout Sing construct\n;val 100;}Sing(const Sing) delete;Sing operator (const Sing) delete; public:int val; };extern std::unique_ptrSing singletonInst; // 声明,把sing.cpp中的定义暴露给main.cpp// init为sing类的子类output 编译链接运行方式1 g -c ./main.cpp -stdc20 (-std参数可选) g -c ./sing.cpp -stdc20 (-std参数可选) g main.o sing.o -o ./ms ./ms Sing construct get value: 100 Sing destroy编译链接运行方式2 g -c ./main.cpp -stdc20 (-std参数可选) g -c ./sing.cpp -stdc20 (-std参数可选) g sing.o main.o -o ./sm ./sm Sing construct get value: 100 Sing destroy从上边结果可以看出无论什么样的链接顺序都可以正常运行那是不是这种实现方式已经完全没有问题了? 不是的下边的变种将会说明这一点 代码部分2 三个文件: main.cpp sing.cpp 和sing.h main.cpp #include sing.hstatic Sing::Init init; auto singletonInst2 singletonInst-val;int main(int argc, char** argv) {std::cout get value: singletonInst2 \n;std::cout singletonInst.get() std::endl;std::cout singletonInst-val std::endl;return 0; }sing.cpp #include sing.h #include memory #include iostreamMyUniquePtrSing singletonInst;Sing::Init::Init() {if (!singletonInst){singletonInst.reset(new Sing());} }sing.h #pragma once #include iostream #include memoryclass Sing { public:struct Init{Init();Init(const Init) delete;Init operator (const Init) delete;};public:~Sing(){std::cout Sing destroy\n;}private:Sing(){std::cout Sing construct\n;val 100;}Sing(const Sing) delete;Sing operator (const Sing) delete; public:int val; };template typename T class MyUniquePtr : public std::unique_ptrT { public:MyUniquePtr() : std::unique_ptrT() {} };extern MyUniquePtrSing singletonInst;output 编译链接运行方式1: g -c ./main.cpp g -c ./sing.cpp g main.o sing.o -o ./ms Sing construct get value: 100 0 Segmentation fault (core dumped) 段错误编译链接运行方式2: g -c ./main.cpp g -c ./sing.cpp g sing.o main.o -o ./sm Sing construct get value: 100 0x56457bcd1eb0 100 Sing destroy这个例子与上一个例子的实现方式是一致的不同点在于单例对象的类型不同前者对象是unique_ptr类型后者是unique_ptr的派生类型。然而就是因为使用了unique_ptr的派生类型MyUniquePtr就出现了链接的时候翻译单元main.cpp在前sing.cpp在后时出现了单例调用前未定义的问题。 这是什么原因呐? 在解释这个问题之前需要明白不同类型对象的初始化时间和初始化类型在这里辨析编译期初始化零初始化和缺省初始化的区别: 编译期初始化: c中常见的编译器初始化包括但不限于常量表达式(constexpr, 凡是被constexpr修饰的函数和变量都可以在编译期实现初始化但是具体也要取决于编译器的类型因为有些编译器会选择在运行初始化constexpr)枚举类型enum和模板元编程等。也就是在编译期就完成了计算并将对应的结果存起来在运行期的时候直接使用。 编译期初始化分为两种constexpr和constevalconstexpr修饰的函数意思是可以在编译期被调用也可以选在在运行期被调用但是具体什么时候被调用是取决于使用的编译器种类consteval修饰的函数意思是可以编译器被调用并且必须在编译期调用。如果定义一个实例对象这个对象的构造函数被consteval修饰那么一定在编译期系统就会计算出这个对象的值存起来在运行的时候直接完成两者的联系。 零初始化: 指在变量声明时将其初始化为零或默认值的行为。在C中如果没有显式提供初始化值那么内置类型的变量将被初始化为零而自定义类型的变量将调用其默认构造函数进行初始化。 缺省初始化: 缺省初始化与零初始化在自定义类型上的行为一致也会调用默认构造函数来初始化成员变量。如果成员变量没有在构造函数中显式初始化那么它们将保持未定义的状态。 运行期初始化与编译期初始化 对于在运行期才初始化的对象采用的初始化方式是零初始化和缺省初始化。在编译的时候系统首先计算这个对象所需的内存空间然后将这块内存里边的所有内容都改为0这就完成了零初始化的过程也就是说这个实例对象指向了内容全为0的一块内存A。随后在运行的时候当轮到该对象的定义初始化的时候然后进行该对象的缺省初始化缺省初始化会让该对象指向悬空也就是指针P没有具体的指向区域是个还没有分配指向的空指针。 例子2中如果链接的时候main.o在前sing.o在后。因为singlentonInst的类型是unique_ptr的拓展类构造函数不是constexpr类型的(因此是运行期初始化进行零初始化和缺省初始化的操作)。所以编译器首先完成了sing.cpp中的对象singlentoninst的零初始化也就是是这个对象指向一开内存都是0的空间。然后在mian.cpp中调用init使得对象singlentonInst指向一块新的有内容的区域(其中有val100)。然后进入sing.o完成singlentonInst的缺省初始化使得对象悬空(未定义,指针未分配)所以指向为空(0),输出singletonInst-val的时候出现段错误。 例子1不会因为链接顺序出问题是因为抽象类型unique_ptr的默认构造函数被constexpr修饰g编译默认constexpr类型构造函数在编译期被调用实现了对象的编译期初始化。 实现方式评注与思考 对于在运行期才初始化的对象采用的初始化方式是零初始化和缺省初始化。在编译的时候系统首先计算这个对象所需的内存空间然后将这块内存里边的所有内容都改为0这就完成了零初始化的过程也就是说这个实例对象指向了内容全为0的一块内存A。随后在运行的时候当轮到该对象的定义初始化的时候然后进行该对象的缺省初始化缺省初始化会让该对象指向悬空也就是指针P没有具体的指向区域是个还没有分配指向的空指针。 实现方式2与1的区别就在于使用的对象类型是unique_ptr的派生类型因为这个派生的指针类型构造函数不能在编译器被调用所以链接的时候main.o在前sing.o在后就会出现sing中对象缺省初 初始化的时候造成了对象指针悬空。如果要正常运行要么就是在这个构造函数前加上关键字constexpr(c11后就可以用)或者consteval(C20才能用)。要么就是在sing.cpp中的singletomInst对象定义后边就上一句init的调用。 为了防止出现第四品中出现的运因为翻译单元main.o链接在sing.o前出现的singletonInst单例未初始化就被调用造成的静态初始化灾难。通过引入初始化类初始化类作为单例类的子类可以访问单例类的所有成员。然后通过初始化类的实例作为纽带一定程度上控制初始化顺序。无论两个翻译单元连接顺序谁先谁后因unique_ptr和init实例在调用singletonInst前边,就避免了静态实例初始化灾难 在C中,一个翻译单元的变量定义顺序有规定但是不同的翻译单元的顺序没有规定。第四品的问题是可能会出现两个翻译单元链接顺序先后问题造成的静态实例灾难。在本次实现1中(编译器实现unique_ptr对象的编译期初始化的话)就不在依赖两个翻译单元的链接顺序。 main.cpp中 初始化类的定义 限定为static是因为在大项目中可能会出现其他cpp文件中也用到同样名字在链接的时候就会出错 init是sing类的子类,完整的继承sing类的所有函数所以在sing.cpp的init函数构造函数中使用new Sing的时候可以调用私有构造函数。 缺点: 这种实现方式存在未定义的问题即便是实现1也会因为编译器的不同出现问题如果某个编译器没有让constexpr修饰的unique_ptr对象的构造函数在编译期被调用完成对象的编译期初始化那么也会出现问题。 下一品的设计思考 下一品将解决这种因为链接顺序造成的未定义问题。
http://www.hkea.cn/news/14376968/

相关文章:

  • 深圳宝安网站推广网站更名策划方案
  • 宁夏政务大厅城乡建设厅口网站关于网站建设公司大全
  • 茂名市城乡和住房建设局网站国外网站代做
  • 网站做支付宝和网银接口天猫商城官网下载
  • 彩票销信 网站怎么做百度 医疗网站建设
  • 福州网站制作好的企业注册资本1000万的公司需要多少钱
  • 赶集的网站怎么做做设计网站的工作内容
  • 建设电子元器件网站python 做企业网站
  • 小企业网站建设哪些好办营销推广有哪些步骤
  • 网站开发制作阶段的说课稿在线建设网站制作
  • 三明网站建设网站改版建议策划书
  • asp.net 网站开发 pdf上榜网络
  • 凡客优品家居官方网站企业信息的网站
  • 移动网站设计尺寸亚马逊网站首页
  • 天门网站定制公司注册有限公司
  • 个人做网站 优帮云建立一个团购网站需要多少钱
  • 简历网站后怎样才能被谷歌 百度收录吗网站分析论文
  • 临邑县住房和城乡建设局网站php做的网站有哪些
  • 郑州便宜网站建设做网站需要学哪些语言
  • 网站 图片防盗链电子商务网站规划建设方案
  • 网站管理员密码忘记了怎么办百度答主招募入口官网
  • 今科网站建设费用南昌集团制作网站设计
  • 网站空间费价格wordpress中文版好还是英文版好
  • c#做的网站怎么上传图片建设企业网站价格
  • 在那里做网站建站用什么工具
  • 旅游电子商务网站标识设计师
  • 府网站建设先进个人高密市建设局网站
  • phpstudy2016快速搭建网站采购系统
  • 中山手机网站建设费用网站排名查询系统
  • 艺之都网站建设微信app开发南宁网站制作系统