首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

摘要

保持(初始化)顺序:不同编译单元中的名字空间级对象决不应该在初始化上互相依赖,因为其初始化顺序是未定义的。这样做会惹出很多麻烦,轻则在项目中稍做修改就会引发奇怪的崩溃,重则出现严重的不可移植问题——即使是同一编译器的新版本也不行。

讨论

在不同的编译单元中定义两个名字空间级的对象时,先调用哪一个对象的构造函数是没有定义的。经常(但并非总是)工具可能会碰巧按照编译单元目标文件的连接顺序初始化,但这种假设并不总是可靠的;即使确实如此,你总不会希望自己代码的正确性难以捉摸地依赖于makefile或者项目文件吧。(更多顺序依赖的恶果,另见第59条。)

因此,在任何名字空间级对象的初始化代码中,不能假设其他编译单元中定义的任何其他对象都已经初始化了。这些考虑方法也适用于动态初始化的原始类型变量,比如名字空间级的bool reg_success = LibRegister("mylib");

请注意,甚至在使用构造函数构造之前,名字空间级对象就已经用0静态初始化过了(与自动对象等初始时包含无用数据相反)。有些自相矛盾的是,这种零初始化会使错误更难以检查,因为静态的零初始化不会迅速使程序崩溃,而是使未初始化对象显现出一种看似合法的表象。你可能认为字符串是空的,指针是空的,整数型变量为0,而事实上,代码已经费劲地将它们初始化了。

为了避免这一问题,应该尽可能地避免使用名字空间级的变量,它们很危险(见第10条)。如果确实需要可能依赖于另一个变量的此种变量,可以考虑使用Singleton(单体)设计模式;使用时要小心一些,可以通过确保对象在第一次访问时被初始化,来避免隐含的依赖性。Singleton本质上也是全局变量——披着羊皮的“狼”(另见第10条),它会因为相互依赖或者循环依赖而被破坏(同样,零初始化只会使情况更复杂)。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论