zoukankan      html  css  js  c++  java
  • 《C++ Primer Plus》学习笔记3

    《C++ Primer Plus》学习笔记3

    第8章 函数探幽

    ===================================================================================================================
    1、C++内联函数和常规函数
    1)常规函数调用使程序跳到还有一个地址(函数地址),并在函数结束时返回。详细过程是运行到函数调用指令时,程序将在函数调用后马上储存指令的内存地址,并将函数參数赋值到堆栈,跳到标记函数起点的内存单元。运行函数代码,之后跳回到地址被保存的指令处。


    2)内联函数无需跳到还有一个位置处执行代码。所以执行速度比較快,可是代价是占用很多其它的内存。

    用对应的代码替换函数的调用,仅仅有在函数非常短时才干採用内联方式。
    要使用内联函数我要必需要採用以下措施之中的一个:
    ①在函数声明前加上keywordinline
    ②在函数定义前加上keywordinline
    通常我们都直接省略原型,直接放在最前面

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

    3)内联和宏
    inline是c++的新增的特性,C语言中通过使用预处理语句#define来提供宏。这个事实上是内联代码的原始实现,这里须要注意宏并非通过传递參数来实现的,而是通过文本替换来实现的。宏不能按值传递

    #define SQUARE (x) X*X
    改进:#define SQUARE (x) (X*X)
    

    所以我们想到以后用宏的时候要想到装换为内联函数。
    2、引用
    1)引用不同于指针,出了写法不一样。还有其它的区别,比如引用必须在声明引用时将其初始化。而不能像指针那样,先声明再复赋值

    int rats = 101;
    int & rodents = rates;
    int * prats = &rates;
    

    以下错误写法:

    int rat;
    int & rodent;
    rodent = rat;
    

    3、按值、按引用、按指针传递的比較:

    //按引用传递
    void swapr(int &a, int  &b)
    {
        int temp;
    
        temp = a;
        a = b;
        b = temp;
    }
    //按指针传递
    void swapp(int *p, int *q)
    {
        int temp;
    
        temp = *p;
        *p = *q;
        *q = temp;
    }
    //按值传递
    void swapv(int a,int b)
    {
        int temp;
        temp = a;
        a = b;
        b = temp;
    }
    

    比較按引用传递和按值传递
    ①声明函数的方式不一样
    ②在引用传递中,由于我们a,b就是别名,所以变换a和b的值。也就相当于变调用函数的值,可是对于值传递中,变量a,b是属于复制了调用函数的变量,所以变换a,b的值并不会改变原调用函数的值,所以这样的传送方式不行。


    比較按引用传递和按指针传递
    ①声明方式不一样
    ②指针传递方式中须要在函数使用p,q的整个过程中使用解除引用操作符*
    swapr(wallet1, wallet2); 即将形參a和b分别初始化为wallet1和wallet2;
    4、暂时变量、引用參数、const
    以下三种情况要尽可能使用const
    ①使用const能够避免无意中改动数据的编程错误
    ②使用const是函数可以处理const和非const实參,否则将仅仅能接受非const数据
    ③使用const引用使函数可以正确生成并使用暂时变量。所以应该尽可能将引用形參声明为const.
    5、使用引用參数的主要原因有两个:
    1)程序猿可以改动调用函数中的数据对象
    2)通过传递引用而不是整个数据对象,能够提高程序的执行速度。
    6、引用參数实际上是基于指针的代码的还有一个接口
    对于使用传递的值而不作改动的函数:
    1)假设数据对象非常小,如内置数据的类型或者小型结构,则按值传递
    2)假设数据对象是数组。则使用指针,由于这是唯一的选择,而且将指针声明为指向const的指针。
    3)假设数据对象是较大的结构。则使用const指针或const引用,以提高程序的效率,这样能够节省复制结构所须要的时间和空间。


    4)假设数据对象是类对象,则使用const引用。传递类对象的标准方式是按引用传递
    7、对于带參数列表的函数,必须从右向左加入默认值,也就是说要为某个參数设置默认值,则必须为它右边的全部參数提供默认值。

    int harpo(int n, int m = 4, int j = 5); //有效
    int chico(int n, int m = 6, int j);     //无效
    int groucho(int k = 1, int m = 2, int n = 3); //有效
    

    注意实參是按从左到右的顺序依次被赋给对应的形參,而不能跳过不论什么參数

    beeps = harpo(3, ,8) //无效
    

    8、默认參数
    默认參数指的是当函数调用中省略了实參时自己主动使用的一个值,为1.

    //返回一个新的字符串包括前字符串的n个字符.cpp
    char *left(const char * str, int n)
    {
        if(n < 0)
            n = 0;
        char *p = new char[n+1];
        int i;
        for(i = 0; i < n && str[i]; i++)
            p[i] = str[i];
        while(i <= n)
            p[i++] = '';
        return p;
    }
    

    9、函数重载
    1)函数重载的关键是函数的參数列表,也称为函数特征标。定义名称同样的函数,条件就是它们的特征标不同。
    (函数特征标指假设两个函数的參数数目和类型同样,同一时候參数的排列顺序也同样,则它们的特征标同样,而变量名是无关紧要的)假设參数数目和或者參数类型不用,那么特征标也不同。

    void print(const char * str, int width);
    void print(double d, int width)
    void print(long l, int width)
    void print(int i, int width)
    void print(const char *str)
    

    2)举例,前面我们讲了一个char left(const char str, int n)
    所以我们编写一个与前面特征标不同返回整数前n个

    //left()返回整数的前几位
    unsigned long left(unsigned long num, unsigned ct)
    {
        unsigned digits = 1;
        unsigned long n = num;
    
        if(ct == 0 || num == 0)
            return 0;
    
        //利用除法来计算数位
        while(n /= 10)
            digits++;
    
        //每除去10就删除数字的最后一位,要知道须要删除多少位。仅仅须要将总位数减去要获得的位数就能够
        if(digits > ct)
        {
            ct = digits - ct;
            while(ct--)
                num /= 10;
            return num;
        }
        else
            return num;
    }
    

    3)尽管函数重载比較诱人,可是不要滥用。仅仅有当函数基本运行同样任务。但使用不同形式的数据时,才採用函数重载。


    10、函数模板
    如今的C++编译器实现了C++新增的一项特性,叫做函数模板,函数模板是通用的函数描写叙述,也就是说它使用了通用类型来定义函数。

    假设须要多个将同一个算法用于不同类型的函数。我们使用模板。

    //交换模板1.cpp
    template <class Any>  //temoplate <typename Any>
    void Swap (Any &a, Any &b)
    {
        Any temp;
        temp = a;
        a = b;
        b = temp;
    }
    //交换模板2——交换两个数组中的元素
    template <class Any>
    void Swap(Any a[], Any b[], int n)
    {
        Any temp;
        for(int i = 0; i < n; i++)
        {
            temp = a[i];
            a[i] = b[i];
            b[i] = temp;
        }
    }
  • 相关阅读:
    android studio遇到的一系列问题
    flask接口入门实现简单的登录注册(二)
    flask接口入门实现简单的登录注册(一)
    第一节:django环境 模型 视图 后台
    设计模式二:建造者模式
    设计模式一:工厂模式
    mysql系列:创建数据库和用户及赋权
    mysql系列:mysql的数据类型
    mysql系列:数据库范式与mysql引擎
    mysql系列:centos7.6上安装mysql8.0
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6817642.html
Copyright © 2011-2022 走看看