• 读书笔记


    • 尽量以const,enum,inline替换#define
      •   用宏定义一个常量的时候,可能会发生一些错误。当发生错误的时候你可能并不能知道这个错误具体出自哪里,因为宏定义的变量可能没有进入记号表中(symbol table)。还有就是宏定义的东西可能会盲目的置换代码中的变量(直接全部置换过去,括号可能会影响最终的结果),会导致出错。
      •   当我们要定义一个常量去替换#define时,有两种情况
        •   ①定义一个指向常量的常量指针,可以这么定义:const std::string author(''fuzhiqiang'')
        •   ②定义一个class专属常量,#define不具有封装性,不能够定义class类的专属常量
      •   枚举enum在很多地方和#define很像。他们都是不允许去得到他们的一个地址。而const取地址是合法的。
      •   但是#ifdef和#ifndef控制编译功能十分重要
      • 对于单纯的常量,最好用const或者enum;对于形似函数的宏最好用inline函数


    • 尽可能使用const
      •   指针使用const
        •   常量指针:char* const pContent  ,是一个指针,它指向的内容是不能变的,但是*pcontent可以改变,通过改变*pcontent可以改变它所指的值
        •   指针常量:const char *pContent,指针所指向的内容是常量,不能改变,就是*pcontent不能改变,pcontent可以改变
        •   指向常量的常量指针:const char* const pContent,都不能改变
      •   函数使用const
        •   参数为引用,为了增加效率同时防止修改。修饰引用参数时:

            void function(const Class& Var); //引用参数在函数内不可以改变

            void function(const TYPE& Var); //引用参数在函数内为常量不可变

          这样的一个const引用传递和最普通的函数按值传递的效果是一模一样的,他禁止对引用的对象的一切修改,唯一不同的是按值传递会先建立一个类对象的副本, 然后传递过去,而它直接传递地址,所以这种传递比按值传递更有效.另外只有引用的const传递可以传递一个临时对象,因为临时对象都是const属性, 且是不可见的,他短时间存在一个局部域中,所以不能使用指针,只有引用的const传递能够捕捉到这个家伙.

      •   类使用const
        •   const修饰成员变量:修饰的成员变量不能被修改
        •   const修饰成员函数:const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。常成员函数, 它不改变对象的成员变量,也不能调用类中任何非const成员函数。
        • 对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的使用。
          a. const成员函数不被允许修改它所在对象的任何一个数据成员。
          b. const成员函数能够访问对象的const成员,而其他成员函数不可以。
      •   将const类型转换为非const类型
        • 用法:const_cast <type_id>  (expression) 
          该运算符用来修改类型的constvolatile属性。除了const volatile修饰之外, type_idexpression的类型是一样的。


      •   建议  
        •   要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;
        •   要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;
        •   在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;
        •   const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;
        •   不要轻易的将函数的返回值类型定为const;
        •   除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;
        •   任何不会修改数据成员的函数都应该声明为const 类型。

    • 确定对象在被使用前已经被初始化
      •   array的内容没有初始化,而vector的内容确是初始化了的
      •   内置类型:bool,char,w_char,short,int,long,float,double,long double;这些初始化都手动完成
      •   类的初始化:一般采用成员列表初始化,而不是单一的赋值
      • class myclass{
        private:
            string Name;
            int Id;
            string Sex;
        public:
            myclass(cosnt string & name,cosnt int & id,const string & sex):
                Name(name),Id(id),Sex(sex){}
        };
        View Code
        •   这其中初始化的次序有讲究的:按照变量声明的次序来进行成员列表初始化
      •   不同的编译单元内定义的  non-local static变量
        •   这里先解释一下名词,static是静态的意思,表示这个变量不由栈分配,而存储在特有的全局变量/静态变量区域中,具有长寿命的特点(从被构造出来,直到程序结束时,才会由系统释放资源);而non-local则是说这个对象是全局的,而不是函数内的静态变量,是说它的作用范围广。
        • 比如在文件1中定义了

          int a = 1;

          而在文件2中又会去使用:

          extern int a;
          int b = a *3;

          可以看到文件1应在文件2之后执行,这样a才能获得初值,否则b得到的将是垃圾值,但事实上C++对于不同文件执行的相对次序并无明确定义,这样b究竟得到的是垃圾值还是3就不能确定。

          解决这个问题是方法是不要使变量有全局的作用域,可以在文件1中定义:

          1 int& GetA()
          2 {
          3          static int a = 1;
          4          return a;
          5 }

          而在文件2中调用

          int b = GetA();

          这样就一定保证a的初始化在先了。

  • 相关阅读:
    软件开发之需求调研方法论
    系统设计之编码概述
    unix/linux共享库(动态库)简介
    unix/linux静态库简介
    pytest的使用
    c语言中static的作用
    awk文本处理
    shell基本概念
    shell i/o交互及重定向
    shell常用分隔符及管道的用法
  • 原文地址:https://www.cnblogs.com/Kobe10/p/5735541.html
Copyright © 2020-2023  润新知