C++新增的引用
1、引用介绍
(1)引用的经典案例:实现swap函数实战
#include <iostream>
using namespace std;
void swap1(int a, int b);
void swap2(int *pa, int *pb);
void swap3(int &pa, int &pb);
int main(void)
{
int x = 4, y = 6;
swap1(x, y);
swap2(&x, &y); // &在这里是取地址符
swap3(x, y);
cout << "x = " << x << ", y = " << y << endl;
return 0;
}
// 不成功
void swap1(int a, int b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
// 成功,用指针
void swap2(int *pa, int *pb)
{
int tmp;
tmp = *pa;
*pa = *pb;
*pb = tmp;
}
// 成功,用引用
void swap3(int &pa, int &pb) // &在这里是引用标识符
{
int tmp;
tmp = pa;
pa = pb;
pb = tmp;
}
(2)引用定义和识别的关键:&符号,注意这里和取地址一毛钱关系都没有
(3)引用符号(注意我没说变量)在定义时必须同时初始化,以后不能再另外赋值,只能使用
#include <iostream>
using namespace std;
int main (void)
{
int a = 2;
int &b = a;
b = 3;
cout << b << endl; //b = 3,可以通过a的引用符号b来改变原来a 的值
return 0;
}
2、引用和指针的对比
(1)指针在C和C++中都有,且使用方法和实现本质完全相同;引用只有C++可用
(2)引用可以理解为功能弱化、安全性增强的低配版指针
(3)引用能做的事指针都能做,但指针能做的事儿引用不一定能做
(4)引用是它指向变量的“别名”,这个是从引用的使用效果角度讲的,对熟悉指针的人反而不好理解“别名”这个词
(5)引用比指针弱的地方就是一个引用定义时绑定了一个变量,后面没法改了
(6)引用比指针强的地方也是没法改,所以不存在"野指针"问题,更安全
(7)引用主要用在函数传参和返回值
3、引用可以加const修饰
(1)const int &b = a; 表示b是a的const别名,无法通过b修改a了
注:int const *p 等价于const int *p ,都表示p指向的空间是const的;而int * const p 表示p本身是const的。
int x = 4;
const int &b = x; // 定义了一个引用符号叫b,关联到x
//b = 44; // 编译时报错
x = 44; // 编译可以,运行也可以
(2)主要用在函数形参中,告诉大家该函数内部不会修改实参的值。用在某些时候我们有一个非const类型的变量,但是我们在某个函数调用的过程中,不希望变量的值在函数内部被修改,这时候就可以用const引用来传参。
int func(const char &p1, const char &p2)
char a1 = 'A', a2 = 'b';
const char &ra1 = a1;
const char &ra2 = a2;
func(ra1, ra2); // 在func内部肯定不会修改ra1和ra2(a1和a2)
a1 = 'B'; // 实际上a1和a2并不是const的,是可以修改的
4、引用的本质是const指针
(1)int &b = a; 等价于 int * const b = &a;也就是说b本身是const的,也就是为什么引用定义时要初始化,而且一旦初始化之后就不能另外赋值。
(2)C++标准并没有规定引用是否占用内存空间,但是大多数编译器都把引用实现为const指针,所以大部分编译器中引用也是要占内存空间的
(3)引用是天然const的,所以定义时必须初始化指向变量,否则就没意义了
(4)引用本质是指针,是地址,所以才能实现传址调用的效果
总结:引用就是指针在定义时增加了把指针变量本身const化
5、引用和sizeof运算符
(1)sizeof引用得到的不是引用本身的大小,而是引用指向的目标变量的大小
(2)在struct或class中定义一个引用,再sizeof整个struct或class就会不一样
#include <iostream>
using namespace std;
struct ints1
{
int a; // 元素1,int类型,在我的64位Ubuntu系统中,占4字节
int &b; // 元素2,int &类型,本身是指针类型,在我的64位Ubuntu系统中指针是占8字节
};
struct chars1
{
char a; // 元素1,char类型,在我的64位Ubuntu系统中,占1字节
char &x; // 元素2,char &类型,本身是指针类型,在我的64位Ubuntu系统中指针是占8字节
};
int main(void)
{
cout << sizeof(struct ints1) << endl;
cout << sizeof(struct ints1) << endl;
cout << sizeof(struct chars1) << endl;
int a = 4;
double b = 5.5;
char c = 'A';
int &ra = a;
double &rb = b;
char &rc = c;
cout << sizeof(rc) << "--" << sizeof(char) << endl;
cout << sizeof(ra) << "--" << sizeof(int) << endl;
cout << sizeof(rb) << "--" << sizeof(double) << endl;
int *p = nullptr; //在c++11标准起,编译时加上-std=c++11
cout << sizeof(p) << endl; //8
return 0;
}