1&引入
c/cpp中用&取变量的地址,但是从cpp赋予了一个新含义
引用是变量的别名,和变量本身是一回事
int a = 10;int c = 9;int& b = a; //引用必须初始化,后期不能更改指向,但是值可以改cout << a << " " << &a << endl;cout << b << " " << &b;b = c; //等价b=9 不过就是赋了一个新值//&b = c; err
2本质
本质就是:指针常量:int* const p=&a(不能修改指向,但可以修改值,不初始化会报错)
对于编译器:就是字符串替换,int&=int&* const……
但是函数传参时,二者要区分开传
引用做函数返回值
#include<iostream>
using namespace std;
//局部变量引用做返回值
int& test1()
{int a = 10; //这样搞虽然不报错,但是本质上不严谨,在别的编译器上就没用了 要么全局变量/要么static关键字return a;
}void quote_return()
{int& i = test1();cout << i << endl; //第一次正确:编译器做了保留cout << i << endl; //第二次一般就错了,因为局部变量a就已经释放了//函数返回值可以做左值test1() = 100;cout << i << endl;cout << i << endl;
}int main()
{quote_return();return 0;
}
值传递&地址传递&引用传递
函数形参声明为引用,调用函数时,形参将成为实参的别名
#include<iostream>
using namespace std;
//值传递_形参不修饰实参 void f(int a)
{a = 10;
}//地址传递_形参修饰实参 &比*方便简单,不需要*解引用和&传参
void quote(int &sum)
{sum = 66;
}void pointer(int*a)
{*a = 99;
}void quote_parameter()
{int a = 1;cout << "值传递前:" << a << endl;f(a);cout << "值传递后:" << a << endl;cout << "quote传参前:" << a << endl;quote(a);cout << "quote传参后:" << a << endl;a = 1;cout << "pointer传参前:" << a << endl;pointer(&a);cout << "pointer传参后:" << a << endl;
}
高纬指针补习(最好自己画图)
#include<iostream>
using namespace std;int main()
{int a = 10;int* p = &a; //p的值就是a的地址;p的值的值就是aint** p2 = &p; //p2的值就是p的地址;p2的值的值就是p的值,就是a的地址……cout << "a的地址:" << &a << " a的值:" << a << endl;cout << "p的地址:" << &p << " a的地址:" << p << " a的值:" << *p << endl;cout << "p2的地址:" << &p2 << " p的地址:" << p2 << " a的地址:" << *p2 << " a的值:" << **p2 << endl;return 0;
}
二级指针传参
#include<iostream>
using namespace std;void f1(int** p) //形参是二级指针,实参是指针地址
{*p = new int(3); //*p就是一级指针的值cout << "f1: p的值:" << *p << " p的值的值:" << **p << endl;
}void f2(int*& p) //形参是指针的别名,实参是指针
{p = new int(3); //让我们p重新指向一块空间,并且赋值为3cout << "f2: p的值:" << p << " p的值的值:" << *p << endl;
}int main()
{int* p = nullptr;//f1(&p);f2(p);cout << "main: p的地址:" << p << " p的值:" << *p << endl;return 0;
}
引用形参和const
加上const在函数体内也就不能修改了
当引用数据类型不匹配,当引用为const,C++会创建一个临时变量,让引用指向临时变量 :
int a = 10;//int& b = 10; err 因为10是常量,内存没有分配地址const int& b = 10; //等价于:int t=10; const int& s=t;int& b = a;
什么时候创建?
1引用是const
2数据对象类型正确,但不是左值(例如上面的10,不能是字符串)
3数据对象类型不正确,但可以转换为正确的类型(例如上面的10,还可以是一个字符)
#include<iostream>
using namespace std;void f1(int* a)
{cout << *a << endl;
}void f2(const int& a)
{cout << a << endl;
}int main()
{//f2(1); //在f2形参+const前这个就报错//f1(1); //指针没有这个特权;加不加const一样报错int a = 10;f2(1);f2(a);return 0;
}
用const的理由:
1用const可以避免无意中修改数据
2可以接收const和非const实参,否则只能接收非const实参
左值补习
左值:可以被引用的数据对象,可以通过地址访问,等号左边
非左值:字面常量(除了字符串,因为字符串常量有地址)和多项表达式