高质量C /C编程指南---第11章 别的编程经历

第11章 别的编程经历

11.1 应用const提高函数的强健性

看到const关键字,C 程序员起首想到的可所以const常量。这可不是精良的前提反射。如果只知道用const界说常量,那么相等于把火药仅用于制造鞭炮。const更年夜的魅力是它可以修饰函数的参数、前去值,甚至函数的界说体。

const是constant的缩写,“恒定稳定”的意思。被const修饰的器材都遭到逼迫回护,可以预防不测的改观观,能提高程序的强健性。所以许多C 程序设计书本建议:“Use const whenever you need”。

 

11.1.1 用const修饰函数的参数

如果参数作输出用,不论它是什么数据范例,也不论它采取“指针转达”还是“援用转达”,都不能加const修饰,否则该参数将失落去输出遵守。

const只能修饰输出参数:

u       如果输出参数采取“指针转达”,那么加const修饰可以避免不测地改动该指针,起到回护浸染。

譬喻StringCopy函数:

        void StringCopy(char *strDestination, const char *strSource);

此中strSource是输出参数,strDestination是输出参数。给strSource加上const修饰后,如果函数体内的语句试图改动strSource的内容,编译器将指腐化误。

 

u       如果输出参数采取“值转达”,由于函数将自动爆发且则变量用于复制该参数,该输出参数正本就无需回护,所以不要加const修饰。

譬喻不要将函数void Func1(int x) 写成void Func1(const int x)。同理不要将函数void Func2(A a) 写成void Func2(const A a)。此中A为用户自界说的数据范例。

 

u       搪塞非外部数据范例的参数而言,象void Func(A a) 如许声明的函数注定遵守比拟底。由于函数体内将爆发A范例的且则工具用于复制参数a,而且则工具的组织、复制、析构进程都将耗费时候。

为了提高遵守,可以将函数声明改为void Func(A &a),由于“援用转达”仅借用一下参数的别名罢了,不需求爆发且则工具。但是函数void Func(A &a) 存在一个缺陷:“援用转达”有可以改动参数a,这是我们不盼望的。治理这个功效很方便,加const修饰即可,因此函数最终成为void Func(const A &a)。

以此类推,能否应将void Func(int x) 改写为void Func(const int &x),以便提高遵守?完全没有需要,由于外部数据范例的参数不存在组织、析构的进程,而复制也希罕很是快,“值转达”和“援用转达”的遵守几乎相等。

    功效是如斯的绸缪,我只好将“const &”修饰输出参数的用法总结一下,如表11-1-1所示。

 

搪塞非外部数据范例的输出参数,应该将“值转达”的方式改为“const援用转达”,目的是提高遵守。譬喻将void Func(A a) 改为void Func(const A &a)。

 

搪塞外部数据范例的输出参数,不要将“值转达”的方式改为“const援用转达”。否则既达不到提高遵守的目的,又降低了函数的可懂得性。譬喻void Func(int x) 不该该改为void Func(const int &x)。

 

表11-1-1 “const &”修饰输出参数的划定端方

 

11.1.2 用const修饰函数的前去值

u       如果赐与“指针转达”方式的函数前去值加const修饰,那么函数前去值(即指针)的内容不能被编削,该前去值只能被赋给加const修饰的同范例指针。

譬喻函数

        const char * GetString(void);

如下语句将出现编译错误:

        char *str = GetString();

精确的用法是

        const char *str = GetString();

 

u       如果函数前去值采取“值转达方式”,由于函数会把前去值复制到外部且则的存储单位中,加const修饰没有任何代价。

    譬喻不要把函数int GetInt(void) 写成const int GetInt(void)。

    同理不要把函数A GetA(void) 写成const A GetA(void),此中A为用户自界说的数据范例。

    如果前去值不是外部数据范例,将函数A GetA(void) 改写为const A & GetA(void)确实能提高遵守。但此时千万千万要警惕,必定要搞清楚函数终究是想前去一个工具的“拷贝”还是仅前去“别名”就可以了,否则程序会腐化。见6.2节“前去值的划定端方”。

 

u       函数前去值采取“援用转达”的场合并不多,这种方式普通只出而今类的赋值函数中,目的是为了完成链式表达。

譬喻

    >

    {…

        A & operate = (const A &other);    // 赋值函数

    };

    A a, b, c;         // a, b, c 为A的工具

    …

    a = b = c;            // 正常的链式赋值

    (a = b) = c;      // 不正常的链式赋值,但正当

如果将赋值函数的前去值加const修饰,那么该前去值的内容不容许被改动。上例中,语句 a = b = c依然精确,但是语句 (a = b) = c 则是正当的。

 

11.1.3 const成员函数

    任何不会编削数据成员的函数都应该声明为const范例。如果在编写const成员函数时,失慎编削了数据成员,或许挪用了别的非const成员函数,编译器将指腐化误,这无疑会提高程序的强健性。

以下程序中,类stack的成员函数GetCount仅用于计数,从逻辑上讲GetCount应当为const函数。编译器将指出GetCount函数中的错误。

    >

{

      public:

        void     Push(int elem);

        int     Pop(void);

        int     GetCount(void)  const;  // const成员函数

      private:

        int     m_num;

        int     m_data[100];

};

 

    int Stack::GetCount(void)  const

{
        m_num;  // 编译错误,方案编削数据成员m_num

    Pop();      // 编译错误,方案挪用非const函数

    return m_num;

    }

    const成员函数的声明看起来怪怪的:const关键字只能放在函数声明的尾部,或许是由于别的中心都已经被占用了。

11.2 提高程序的遵守

程序的时候遵守是指运转速度,空间遵守是指程序占用内存或许外存的情况。

全局遵守是指站在整个零碎的角度上思考的遵守,局部遵守是指站在模块或函数角度上思考的遵守。

 

l         【划定端方11-2-1不要一味地寻求程序的遵守,应当在知足精确性、靠得住性、强健性、可读性等质量要素的前提下,设法主见提高程序的遵守。

 

l         【划定端方11-2-2以提高程序的全局遵守为主,提高局部遵守为辅。

 

l         【划定端方11-2-3在优化程序的遵准时,应领先找出限定遵守的“瓶颈”,不要在有关紧急之处优化。

 

l         【划定端方11-2-4先优化数据交友涉算法,再优化实验代码。

 

l         【划定端方11-2-5无意分时候遵守和空间遵守可以统一,此时应当解析那个更严重,作出恰当的折中。譬喻多花费一些内存来提高功效。

 

l         【划定端方11-2-6不要寻求紧凑的代码,由于紧凑的代码并不能爆发高效的机器码。

 

11.3 一些有益的建议

²        【建议11-3-1当心那些视觉上不易分辨的操作符爆发誊写错误。

我们常常会把“==”误写成“=”,象“||”、“&&”、“<=”、“>=”这类标记也很方便爆发“丢1”失落误。但是编译器却不必然能自动指出这类错误。

 

²        【建议11-3-2变量(指针、数组)被创建之后应当及时把它们初始化,以避免把未被初始化的变量当成右值应用。

 

²        【建议11-3-3当心变量的初值、缺省值错误,或许精度不敷。

 

²        【建议11-3-4当心数据范例转换爆发错误。只管即使应用显式的数据范例转换(让人们知道爆发了什么事),避免让编译器轻悄然地终了隐式的数据范例转换。

 

²        【建议11-3-5当心变量爆发上溢或下溢,数组的下标越界。

 

²        【建议11-3-6当心健忘编写错误措置惩程序,当心错误措置惩程序本人有误。

 

²        【建议11-3-7当心文件I/O有错误。

 

²        【建议11-3-8避免编写手段性很高代码。

 

²        【建议11-3-9不要设计面面俱到、希罕很是矫捷的数据组织。

 

²        【建议11-3-10如果原有的代码质量比拟好,只管即使复用它。但是不要修补很差劲的代码,应当重新编写。

 

²        【建议11-3-11只管即使应用尺度库函数,不要“创造”已经存在的库函数。

 

²        【建议11-3-12只管即使不要应用与详细硬件或软件情况干系周详亲密的变量。

 

²        【建议11-3-13把编译器的选择项设置为最严酷情况。

 

²        【建议11-3-14如果可以的话,应用PC-Lint、LogiScope等工具终了代码审查。



版权声明: 原创作品,容许转载,转载时请务必以超链接方式标明文章 原始因由 、作者信息和本声明。否则将究查司法责任。

posted @ 2011-03-07 17:01  蓝色的天空III  阅读(112)  评论(0编辑  收藏  举报