C++基础Day12


Day12.2021.11.19

注意事项:

  • 引用必须初始化

  • 初始化后不可以改变

 
  //引用必须初始化
     int a = 10;
     int b = 20;
     int& c = a;//int &c;是不允许的
 ?
     c = b;//引用是改变不了的,这句话是赋值操作,把b指向那块内存赋值给c指向的内存
     cout << a << endl;//20
     cout << b << endl;//20
     cout << c << endl;//20

引用本质应该是一个指针常量,指针指向的值可修改,指向的内存地址不能改变

引用传递

函数传参时,使用引用简化指针让形参修饰实参

 //值传递
 void swap1(int a, int b) {
     int index = a;
     a = b;
     b = index;
     cout << "a=" << a << endl;
     cout << "b=" << b << endl;
 }
 //地址传递
 void swap2(int* a, int* b) {
     int index = *a;
     *a = *b;
     *b = index;
     cout << "a=" << *a << endl;
     cout << "b=" << *b << endl;
 }
 //引用传递
 //引用传递是起别名,别名和本名指向同一块内存,引用传参相当于把自身传进去改
 void swap3(int& a,int& b) {
     int index = a;
     a = b;
     b = index;
     cout << "a=" << a << endl;
     cout << "b=" << b << endl;
 }
 int main() {
     
     int a = 10;
     int b = 20;
     swap1(a, b);
     cout << a << endl;//10
     cout << b << endl;//20
 ?
     int c = 30;
     int d = 40;
     swap2(&c, &d);
     cout << c << endl;//40
     cout << d << endl;//30
 ?
     int e = 50;
     int f = 60;
     swap3(e, f);
     cout << e << endl;//60
     cout << f << endl;//50
 ?
     system("pause");
     return 0;
 }

引用做函数返回值

注意:不要返回局部变量引用

用法:函数调用作为左值

 //不要返回局部变量的引用
 int& test1() {
     int a = 10;
     return a;
 }
 int& test2() {
     static int a = 10;
     return a;
 }
 int main() {
 ?
     int& b = test1();
     cout << b << endl;//第一次编译器做保留
     cout << b << endl;//栈区的局部变量内存被释放掉了
     
     //这里面做了两次引用,test2()是a的别名,c是test2()的别名,实际上c和test2()都是a
     int& c = test2();
     cout << c << endl;
     cout << c << endl;
     //函数调用可以作为左值
     test2() = 100;
     cout << "c=" << c << endl;
     cout << "test2()=" << test2() << endl;
     //如果函数的返回值是引用,则函数可以作为左值
 }

引用的本质

是指针常量

 void fun(int& ref) {
     ref = 100;//实际上是 *ref=100;
 }
 int main() {
     int a = 10;
     //引用的本质是一个指针常量
     //写成 int* const ref= &a;实际上就是创建了一个指针ref指向a,并且指针指向不可以改
     int& ref = a;
 ?
     ref = 20;
 ?
     cout << "a=" << a << endl;//20
     cout << "ref=" << ref << endl;//20
 ?
     fun(a);
     cout << "a=" << a << endl;//100
     cout << "ref=" << ref << endl;//100
 }

常量引用

修饰形参,防止误操作

 int main() {
 ?
     int a = 10;
 ?
     //int& b = 10;必须引用一块合法的内存空间(这个常量10没开辟空间)
 ?
     //加了const之后,编译器把代码修改为
     //int temp=10;const int& b=temp; 原名不知道
     
     const int& b = 10;
     //b = 20;因为加了const,所以不能修改值
 }

实际场景

 void showNum(int& num) {
 ?
     num = 10000;//不希望改动
     cout <<"num=" << num << endl;
 }
 ?
 int main() {
     int num = 10;
     showNum(num);
 }

代码多的时候容易把实参改了,所以加个const

1.需要首先明确的是,形参改变实参这种情况只可能发生在地址传递或引用传递之中。这里针对的是引用传递的情况;

2. 防止形参改变实参”的意思是:在函数中可能会对形参的值进行修改,由于是引用传递,因此实参也会跟着改变。但是我们有时又不想让实参跟着改变,那么就可以用const来修饰形参。

那么,如果改变形参时不想同时改变实参,为什么不在一开始就使用值传递呢?

这是因为值传递在数据量大的时候会消耗大量的内存,而引用传递可以大大降低内存的使用。

而不加引用,编译器会在函数中给形参也开辟和实参相同大小的空间,这样会占用更多内存。

P94结束