zoukankan      html  css  js  c++  java
  • 学习C++.Primer.Plus 8 函数探幽

    1. 内联函数

    1. 普通函数调用:

        存储调用指令的地址-》将函数参数复制到堆栈-》跳到函数地址执行代码(返回值放到寄存器)-》跳回调用指令处

      2.  当代码执行时间很短,且会被大量调用的时候,使用内联函数将节省调用的时间。

      3.  定义方法:

        省略原型,并将整个定义放在本应该放原型的地方,书写的时候尽量将整个函数放到一行中,如果函数占多行就不太合适作为内联函数。

    inline double square( double x) { return x * x; }

      4.  内联函数不能递归调用。

     2.引用变量

    1. 引用变量的主要用作是用途函数的形参。通过将引用变量用作参数,函数将使用原始数据,而不是其拷贝。(就是一个有多个名称的同一个变量)。
    2. 引用是专门为结构和类设计的,不能用作数组。
    3. 创建引用变量:
        
      int x = 16;
      int & refx = x;

       int & 指的是指向int的引用。
      注:引用必须在声明的时候进行初始化。而不能后来通过赋值来设置
      特别接近于const指针:

      int & rodent = rat;
      //特别接近于下面的代码:
      int * const pr = rats;
    4. 引用传递:
      将引用用作函数参数进行 参数传递的方法
    5. 常量引用:
      引用变量的原值而不对变量做任何修改时,用const。(此种情况下,如果数据比较小时尽量采用值传递,当数据比较大时,采用引用参数将很有用)。
    6. 左值参数:
      可以被引用的数据对象,如变量、数组元素、结构变量、引用和被解除引用的指针等。
      非左值包括字面值常量、包含多项的表达式等。

    7. 如果函数调用的参数 不是左值 或 与相应的const引用的参数不匹配,则C++将创建类型正确匿名变量,将函数调用的参数的值传递给该匿名变量,并让参数来引用该变量。
    8. 允许的条件下尽可能使用const值,可以接受const和非const类型的实参,否则只接受非const实参。
    9. 对于返回值为引用类型的函数,实际上是被引用的变量的别名。
    10. 返回引用的函数不应返回临时变量的引用。如果指向临时变量的引用,函数运行完毕后,它将不复存在,引用就指向了不存在的内在单元中:
      const myStruct & clone(myStruct & stru)
      {
          myStruct tmp = stru;
          return tmp;//错误
      }

      将返回值定义为const myStruct &类型表明不能使用该返回值来修改引用指向的结构。

    11. 引用的形参类型和实参类型不匹配但可以自动转换时,会生成一个临时变量,然后将该临时变量的引用传递给形参。
    12. 基类引用可以指向派生类对象,而无需强制类型转换。
    13. iostream和派生类fstream对象的几个方法:
      ofstream os;
      ios_base::fmtflags initial = os.setf(ios::fixed);//定点表示模式,返回值为fmtflags类型,表示之前的所有格式,以便结束后还原设置
      os.precision(3);//定点模式下显示多少位小数
      os.setf(ios::showpoint);//显示小数点的模式
      os.width(10);//输出的下一个值要占几个字段宽度
    14. 引用与指针的使用场合:
      * 数据对象是数组时,必须使用指针。
      * 如果是结构,则使用 引用 或 指针。
      * 数组对象是小型C++内置的数据类型时,要修改值就用指针,不要修改值的直接按值传递。
      * 如果数据对象是类,则使用引用,这也是引用被增加的原因。

    3.默认参数

    1. 必须通过函数原型来来设置默认值.
      int harpo(int n ,int m = 4, int j = 5);
    2. 而且设置默认值时,必须从右到左依次设置,如果一个参数设置了默认值,那么它的右侧所有的都要设置默认值。
    3. 调用时,不能跳过任何参数,即使使用默认值:
      harpo(3, ,9);//
      harpo(3,5);//省略也是从右到左,中间的不能跳过

    4.函数重载

    1. 函数是否可以重载是根据特征标来判断。
      template <> void Swap<job> (job &, job &);

      特征标是根据函数的 参数(参数类型和排列顺序)来确定的
      并且编译器检查时把 引用类型和类型本身视为同一个特征标,匹配函数时,也不会区分const和非const。
    2. 名称修饰:
      C++编译器对函数名称进行的加密,具体是根据函数的特征标对每个函数名进行修饰。

    5.函数模板

    1. 模板声明:
      template <typename XJP>//考虑向后兼容时,也可以用class XJP。尽量使用typename
      void method (XJP &a, XJP &b)
      {
          XJP tmp;
          tmp = a;
          a = b;
          b = tmp;
      }
    2. 显式具体化模板函数:声明和定义都以template <>开头,并显式指定类型:
      template <> void Swap<job> (job &, job &);

       其中Swap<job>中的<job>是可选的,因为参数列表已经表明类型,所以可以写成这样:

      template <> void Swap (job &, job &);
    3. 对于给定的函数名,可以有非模板函数、模板函数 和 显式具体化模板函数 以及它们的重载版本。
    4. 编译时会根据实际情况生成特定类型的函数,编译器编译后的最终代码不包含任何模板,只包含为程序生成的实际函数。
      这个根据模板生成特定类型函数定义(模板实例)的过程称为隐式实例化
    5. 显式实例化:直接命令编译器创建特别的实例。注意区别:显式实例化不template后不包含<>,而显示具体化后面有。
      template void Swap<int> (int, int);

      也可以省略<int>://是否可省略有待验证

      template void Swap(int, int);

       注:显式实例化是用函数模板生成特定类型的模板实例(函数定义);而显式具体化则是要自己写出类型的函数定义。


      隐式实例化 和 显式实例化 和 显式具体化 统称为具体化,表示的都是使用具体类型的函数定义,而不是通用描述。

    6. 注:在同一编程单元中使用同一种类型的显式实例和显式具体化将出错。
    7. 编译器选择最佳匹配模板的原则是找出“最具体”的函数模板:
      非模板函数 > 显式具体化模板函数  >   普通模板函数
      用于找出最具体的模板的规则被称为  函数的部分排序规则
    8. 如果有多个同样合适的非模板函数或模板函数,但没有一个比其它函数更具体,或者没有一个函数匹配 ,这些情况都是错误的。
    9. 编译器在选择最佳匹配函数时,不考虑返回类型,而只考虑函数的特征标。
      对于参数的匹配选择的优先顺序如下:
      完全匹配   >    提升转换(char到int,float到double等)    >         标准转换(int到char,long到double等)      >    用户定义的转换(如类)
  • 相关阅读:
    LayoutInflater作用及使用--自定义EditText,自带清除内容按钮
    SSL backend error when using OpenSSL pycurl install error
    pypyodbc 的坑
    mongo aggregate 删除重复数据
    如何验证代理ip的正确性
    python的非官方的一个下载lib的地方
    rabbitmq web 管理系统的信息
    内存泄漏分析
    readme 语法
    logging dictconfig
  • 原文地址:https://www.cnblogs.com/yuantf/p/3182622.html
Copyright © 2011-2022 走看看