C++--第2课 - C++中的引用

第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\n", b, sizeof(b));   

    b = 3;

    a = b;   

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

    b = -5;

    a = b;   

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

    a = 10;

    b = a;   

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

    b = 0;  

    printf("b = %d\n", 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\n", b);   

    b++;   

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

    b = b + 1; 

    printf("b = %d\n", 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\n", 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\n", a);

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

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

    printf("&b = %08X\n", &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\n", a);

    printf("b = %d\n", 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\n", 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\n", 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\n", &a);

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

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

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

    printf("sizeof(TRef) = %d\n", 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\n", a);

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

    printf("f() = %d\n", 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  数组引用和数组指针有什么区别?函数引用和函数指针又有什么区别?

猜你喜欢

转载自www.cnblogs.com/free-1122/p/11336150.html