96SEO 2026-02-20 03:12 8
。

造成的原因是因为存在调用单例对象前没有完成定义的问题#xff0c;这一品将着重解…
上一品引入写在前边代码部分1代码部分2实现方式评注与思考下一品的设计思考
第四品中可能会因为翻译单元的链接先后顺序造成静态初始化灾难的问题。
造成的原因是因为存在调用单例对象前没有完成定义的问题这一品将着重解决这个问题。
singletonInst;Sing::Init::Init()
(!singletonInst){singletonInst.reset(new
delete;};public:~Sing(){std::cout
destroy\n;}private:Sing(){std::cout
destroy从上边结果可以看出无论什么样的链接顺序都可以正常运行那是不是这种实现方式已经完全没有问题了?
singletonInst;Sing::Init::Init()
(!singletonInst){singletonInst.reset(new
delete;};public:~Sing(){std::cout
destroy\n;}private:Sing(){std::cout
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对象的编译期初始化的话)就不在依赖两个翻译单元的链接顺序。
限定为static是因为在大项目中可能会出现其他cpp文件中也用到同样名字在链接的时候就会出错
init是sing类的子类,完整的继承sing类的所有函数所以在sing.cpp的init函数构造函数中使用new
这种实现方式存在未定义的问题即便是实现1也会因为编译器的不同出现问题如果某个编译器没有让constexpr修饰的unique_ptr对象的构造函数在编译期被调用完成对象的编译期初始化那么也会出现问题。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback