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等)      >    用户定义的转换(如类)
  • 相关阅读:
    利用dockerfile定制镜像
    发布Docker 镜像到dockerhub
    Docker 停止容器
    133. Clone Graph
    132. Palindrome Partitioning II
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    127. Word Ladder
  • 原文地址:https://www.cnblogs.com/yuantf/p/3182622.html
Copyright © 2011-2022 走看看