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

摘要

一切从白纸开始:未初始化的变量是CC++程序中错误的常见来源。养成在使用内存之前先清除的习惯,可以避免这种错误,在定义变量的时候就将其初始化。

讨论

按照CC++相同的低层高效率传统,通常并不要求编译器初始化变量,除非你显式地这样做(比如,局部变量,构造函数初始式列表中遗漏的成员)。应该显式地初始化变量。

几乎没有理由不对变量进行初始化。实际上没有任何理由值得冒未定义行为可能带来的危险。

使用过程式语言(如PascalCFortranCobol)的人,可能有这样的习惯:独立于使用它们的代码来定义变量,然后在要使用的时候再赋值。这种方式已经过时了,是不可取的(见第18条)。

关于未初始化变量,有一个常见的误解:它们会使程序崩溃,因此通过简单的测试就能很快地发现分布在各处的那些为数不多的未初始化变量。但事实恰恰相反,如果内存布局碰巧满足了程序需求,带有未初始化变量的程序能够毫无问题地运行上数年。在此之后,如果从不同环境中调用,或者重新编译,或者程序的另一个部分进行了修改,都可能导致各种故障发生,轻则出现难以琢磨的行为,重则发生间歇性的崩溃。

示例

1 使用默认初始值或?:减少数据流和控制流的混合。

// 不可取的:没有初始化变量

int speedupFactor;

if( condition )

  speedupFactor = 2;

else

  speedupFactor = -1;

// 较好的:初始化了变量

 

int speedupFactor = -1;

if( condition )

  speedupFactor = 2;

 

// 较好的:初始化了变量

int speedupFactor = condition ? 2 : -1;

在较好的方案中,变量的定义和初始化做到了亲密无间。

2 用函数替代复杂的计算流。有时候计算值的最好方式是将计算封装在一个函数中(见第11条):

// 不可取的:没有初始化变量

int speedupFactor;

 

if( condition ) {

  // ……代码……

speedupFactor = someValue;

}else {

  // ……代码……

speedupFactor = someOtherValue;

}

 

// 较好的:初始化了变量

int speedupFactor = ComputeSpeedupFactor();

3 初始化数组。对于大的聚集类型比如数组,正确的初始化并不总是意味着要真地对所有数据进行操作。例如,假设一个API要求使用大小为MAX_PATH的固定的char数组(另见第77条和第78条)。如果能肯定数组总是被当作以空字符结束的C语言字符串处理的话,这种立即赋值的方式就已经够好了:

// 可以接受:创建一个空路径

char path[MAX_PATH]; path[0] = '\0';

下面这种更安全的初始化则用0填充了数组中的所有字符:

// 更好:创建一个以0填充的路径

char path[MAX_PATH] = {'\0' };

两种方式都是可取的,但一般而言安全性总是优于不必要的效率考虑。

例外情况

硬件或者其他进程直接写入的输入缓冲区数据和volatile型数据不需要程序对其进行初始化。

 

查看所有评论(0)条】

最近评论



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