高质量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等工具举办代码查察。



版权声明: 原创作品,准许转载,转载时请务必以超链接情势标明文章 原始来由 、作者信息和本声明。不然将究查法令责任。

原文地址:https://www.cnblogs.com/zgqjymx/p/1974597.html