zoukankan      html  css  js  c++  java
  • C++--第2课

    第2课 - C++中的引用

    1. C++中的布尔类型

    C++在C语言的基本类型系统之上增加了bool。C++中的bool可以取得值只有true和false,true代表真值,编译器内部用1来表示;false代表非真值,编译器内部用0来表示。理论上的bool只占用一个字节。

    如果多个bool变量定义在一起,可能会各占一个bit,这取决于编译器的实现。

    #include <stdio.h

    int main(int argc, char *argv[])

    {

        int a;

        bool b = true;   

        printf("b = %d, sizeof(b) = %d ", b, sizeof(b));   

        b = 3;

        a = b;   

        printf("a = %d, b = %d ", a, b); 

        b = -5;

        a = b;   

        printf("a = %d, b = %d ", a, b);  

        a = 10;

        b = a;   

        printf("a = %d, b = %d ", a, b);  

        b = 0;  

        printf("b = %d ", b);  

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    b = 1, sizeof(b) = 1

    a = 1, b = 1

    a = 1, b = 1

    a = 10, b = 1

    b = 0

    bool类型只有true(非0)和false(0)两个值。C++编译器会在赋值时将非0转化为ture,0转化为false

    #include <stdio.h>

    int main(int argc, char *argv[])

    {

        bool b = false;   

        printf("b = %d ", b);   

        b++;   

        printf("b = %d ", b);  

        b = b + 1; 

        printf("b = %d ", b);

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    运行结果:

    b = 0

    b = 1

    b = 1

    2. 三目运算符

    #include <stdio.h>

    int main(int argc, char *argv[])

    {

        int a = 1;

        int b = 2;  

        (a < b ? a : b) = 3;  

        printf("a = %d, b = %d ", a, b);  

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    运行结果:a = 3, b = 2

    C语言中的三目运算符返回的是变量值,不能作为左值使用。

    C++中的三目运算符可直接返回变量本身,因此可以出现在程序的任何地方。但是,三目运算符可能返回值中有一个是常量值,则不能作为左值使用。

    3. C++中的引用

    (1)变量名回顾

    变量是一段实际连续存储空间的别名。

    程序中通过变量来申请并重新命名存储空间。

    通过变量的名字可以使用存储空间。

    思考:对于一段连续的存储空间只能有一个别名吗?

    (2)引用

    引用可以看做一个已经定义变量的别名。

    引用的语法:type& name = var;

    tip:普通引用在声明时必须用其他的变量来进行初始化。

    #include <stdio.h>

    int main(int argc, char *argv[])

    {

        int a = 4;

        int& b = a;

        b = 5;

        printf("a = %d ", a);

        printf("b = %d ", b);

        printf("&a = %08X ", &a);

        printf("&b = %08X ", &b); 

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    运行结果:

    a = 5

    b = 5

    &a = 0028FF18

    &b = 0028FF18

    引用的意义:

    引用作为其他变量的别名而存在,因此在一些场合可以代替指针。引用相对于指针来说具有更好的可读性和使用性。

    我们看一下swap()函数的实现对比:

    void swap(int& a, int& b)

    {

        int t = a;

        a = b;

        b = t;

    }

    swap(a, b);

    void swap(int* pa, int* pb)

    {

        int t = *pa;

        *pa = *pb;

        *pb =t;

    }

    swap(&a, &b);

    tip:引用作为函数参数声明时不进行初始化。

    (3)const引用

    在C++中可以声明const引用。

    const Type& name = var;

    tip:const引用让变量拥有只读属性。

    #include <stdio.h>

    int main(int argc, char *argv[])

    {

        int a = 4;

        const int& b = a;

        int* p = (int*)&b;  

        //b = 5;    这段程序有错,因为const引用是只读的。

        *p = 5;   

        printf("a = %d ", a);

        printf("b = %d ", b);  

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    a = 5

    b = 5

    (4)当使用常量对const引用进行初始化时,C++编译器会为常量分配空间,并将引用作为这段空间的别名。

    #include <stdio.h>

    int main(int argc, char *argv[])

    {

        const int& b = 1;

        int* p = (int*)&b; 

        //b = 5;  

        *p = 5;  

        printf("b = %d ", b);  

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    运行结果:b = 5

    使用常量对const引用初始化后将生成一个只读变量。若const常量引用是一个常量,那么它的值是没办法通过指针来改变的。这里的只读变量和C语言中的const变量是只读变量是一样的。

    (5)引用有自己的存储空间

    #include <stdio.h>

    struct TRef

    {

        int& a;

        int& b;

    };

    int main(int argc, char *argv[])

    {

        printf("sizeof(TRef) = %d ", sizeof(TRef)); 

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    运行结果:sizeof(TRef) = 8

    l  引用若是没有自己的存储空间,那么定义的结构体占的内存就会是0。

    l  引用在C++内部的实现是一个常指针:Type& name ---Type* const name

    C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占的空间大小与指针相同。

    从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做的细节隐藏。

    void f(int& a)

    {        a = 5;        }

    等价于

    void f(int * const a)

    {        *a = 5;      }

    我们看一下下面的程序:

    #include <stdio.h>

    struct TRef

    {

        int& a;

        int& b;

        int& c;

    };

    int main(int argc, char *argv[])

    {

        int a = 1;

        int b = 2;

        int c = 3;

        TRef rA = {a, b, c};  

        printf("&a = %08X ", &a);

        printf("&b = %08X ", &b);

        printf("&c = %08X ", &c);

        printf("&rA = %08X ", &rA);

        printf("sizeof(TRef) = %d ", sizeof(rA));  

        printf("Press enter to continue ...");

        getchar();

        return 0;

    }

    运行结果:

    &a = 0028FF1C

    &b = 0028FF18

    &c = 0028FF14

    &rA = 0028FF08

    sizeof(TRef) = 12

    我们看到rA的地址和a, b, c的地址是不同的,而且它还有自己的存储空间。rA和c的地址正好相差了12个字节。

    (6)当喊得的返回值是引用的时候

    若返回栈变量:不能成为其它引用的初始值,不能作为右值使用。

    若返回静态变量或者全局变量:可以成为其他引用的初始值,既可以作为右值使用,也可以作为左值使用。

    #include <stdio.h>

    int& f()

    {

        static int a = 0;  

        return a;

    }

    int& g()

    {

        int a = 0; 

        return a;

    }

    int main()

    {

        int a = g();

        int& b = g();  

        f() = 10;  

        printf("a = %d ", a);

        printf("b = %d ", b);

        printf("f() = %d ", f());  

        printf("Press enter to continue ..."); //若不加这两条代码,程序就会一闪而过。

        getchar();

        return 0;

    }

    运行结果:

    a = 0

    b = -2

    f() = 10

    a的值就是一个简单的函数调用,会将函数g中局部变量a的值给主函数中的a。b引用的是一个已经释放掉的局部变量的别名,相当于b就是函数g中局部变量a的别名,是没有意义的,会随机给值。f的返回值是一个静态局部变量,是可以作为左值使用的,所以可以给函数f赋值10。也就是相当于给它的静态变量赋值10。

    (7)C++对三目运算符做了什么

    当三目运算符的可能但是只都是变量的时候,返回的是变量的引用。

    当三目运算符的可能返回值中有常量的时候,返回的是值。

    int a = 1;

    int b = 2;

    (a < b ? a : b) = 3;  //正确,返回a或b的引用,可以作为右值使用。

    (a < b ?1 : b) = 3;  //错误,可能返回中有常量,返回的是值,不能作为右值使用。

    小结:

    (1)      bool类型是C++新增加的基础类型,它的值只能是true和false。

    (2)      C++中的引用可以看做变量的别名来使用。

    (3)      C++中的常量引用可以使得变量拥有只读的属性。

    (4)      C++中的常引用可以用常量初始化而得到一个只读变量。

    (5)      C++中引用的本质是一个指针常量。

    课后练习:

    l  在C++中为什么不允许引用数组Type& a[N]?

    l  如何定义一个数组的引用?如何定义一个函数的引用?

    l  数组引用和数组指针有什么区别?函数引用和函数指针又有什么区别?

  • 相关阅读:
    H: Dave的组合数组(二分法)
    G: Dave的时空迷阵(next数组)
    计蒜客 X的平方根(二分法)
    最短路径四种方法
    POJ 2001 Shortest Prefixes(字典树活用)
    HDU 1671 Phone List (qsort字符串排序与strncmp的使用 /字典树)
    快速排序原理
    抓捕盗窃犯
    Hash函数
    Monkey King(左偏树 可并堆)
  • 原文地址:https://www.cnblogs.com/free-1122/p/11336150.html
Copyright © 2011-2022 走看看