目录
一.引用
1.1引用和取地址
1.2 别名和原名的区别
1.3 引用的用法
1.31 做参数
1.311 输出型参数:形参改变实参
1.312 可以减少拷贝,增加效率
1.32 引用的约定
1. 引用必须初始化
2. 引用定义后,不能改变指向
4. 给指针取别名
1.33 引用做返回值
错误示范
传值返回:返回a的拷贝
传引用:返回的是a的别名
结论:如果返回变量出了作用域(生命周期(局部变量))就销毁,不能使用引用返回。
1.4 引用和指针的区别
一.引用
引用只是给一个变量重新取了一个名字,取了一个别名,不会给引用重新分配空间。
1.1引用和取地址
引用: 在一个类型的后面加上& 等于一个变量。为取别名
int a = 0;
int& b = a;
取地址:在一个变量前面加上&
cout << &b << endl
1.2 别名和原名的区别
别名=原名。鲁迅就是周树人,他们是等价的,所以对其中一个++,他们都++,所以他们输出的结果是一样的。
int a =0;
int& b =a;
cout << &b <<endl;
cout << &a <<endl;
b++;
a++;
- 别名可以有多个。
- 可以给别名取别名。
1.3 引用的用法
1.31 做参数
1.311 输出型参数:形参改变实参
例如交换两个数的函数,在C语言中,由于形参是实参的拷贝,所以如果想让形参改变实参就要传地址,然后形参用指针接收。
void swap(int* a,int* b)
{
...
}
int main()
{
int x =5;
int y =6;
swap(&x,&y);
}
在C++里就不用,直接用别名,因为别名就等价于原名,对别名的改变就等于改变原名。
void swap(int& a,int& b)
{
int tmp = a;
a = b;
b =tmp;
}
int main()
{
int x =5;
int y =6;
swap(x,y);
}
1.312 可以减少拷贝,增加效率
1.32 引用的约定
1. 引用必须初始化
2. 引用定义后,不能改变指向
3. 一个变量可以有多个别名
4. 也可以给指针取别名
1. 引用必须初始化
int a = 0;
int &b = a;
下面是错误代码,因为引用必须初始化。
int a = 0;
int &b;
b = c;
2. 引用定义后,不能改变指向
int a = 0;
int &b = a;
int c = 2;
b = c; //这里不是改变指向,而是将C的值赋给b
这里b是a的别名,b = c 不是将b的指向从a变为c,而是将C的值赋给b。这是因为引用的指向不能改变。
4. 给指针取别名
下面是C语言写法
void PushBack(struct Node** pphead,int x)
{
*pphead = newnode;
}
int main()
{
Struct Node * plist =NULL;
PushBack(&plist,1);
}
C++写法,可以对指针取别名
void PushBack(int*& phead,int x)
{
}
int main()
{
Struct Node * plist =NULL;
PushBack(&plist,1);
}
1.33 引用做返回值
错误示范
传值返回:返回a的拷贝
下面代码虽然调用了函数,但是并不能返回0;
这就涉及到函数栈帧的问题。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int func()
{
int a = 0;
return a;
}
int main()
{
int ret = func();
cout << ret << endl;
return 0;
}
第一步给主函数创建栈帧,然后是给局部变量ret创建栈帧,再是调用函数func,第四步 是给func创建栈帧,第五步给局部变量a创建栈帧,第六步返回return,但是由于a是局部变量,所以a出了作用域栈帧就销毁了,所以return的将不会是a的值。
传引用:返回的是a的别名
这是& func会是野引用。返回也不是0,而是a的别名,结果是返回一个随机值。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int& func()
{
int a = 0;
return a;
}
int main()
{
int ret = func();
cout << ret << endl;
return 0;
}
结论:如果返回变量出了作用域(生命周期(局部变量))就销毁,不能使用引用返回。
1.4 引用和指针的区别
- 引用大部分功能是一样的,但是引用不能完全代替指针。
- 引用不能代替指针的原因就是:引用的指向不能改变,但是指针可以
- 例如:链表,二叉树等,插入删除。他们的插入删除,涉及到next域的传递改变指向。
1.5 可以用引用返回的情况
返回变量如果出了作用域生命周期就会销毁(即局部变量),不能用引用返回。
可以用引用返回的情况
全局变量/静态变量(static)/堆上变量等