C++回顾day02---<引用>---待补充
一:引用概念---引用就是为一个变量起一个别名
每个变量都是指向一块内存空间的标识,引用就是重新设置一个标识,但是这个标识还是指向同一个内存空间
和指针类似(其实引用本质就是使用了一个常指针 const int* b; 可修改内存值,不可修改指针地址),都可以直接操作同一块内存
但是引用的可读性更好,在一些场合可以代替指针
二:简单使用(同指针一起)
//1.值传递 void swap01(int a, int b) { int temp = a; a = b; b = temp; } //2.指针传递 void swap02(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } //3.引用传递 void swap03(int& a, int& b) { int temp = a; //可读性好些 a = b; b = temp; } void main() { int a1 = 1, b1 = 2; int a2 = 1, b2 = 2; int a3 = 1, b3 = 2; swap01(a1, b1); swap02(&a2, &b2); swap03(a3, b3); cout << "值传递:" << a1 << " " << b1 << endl; cout << "指针传递:" << a2 << " " << b2 << endl; cout << "引用传递:" << a3 << " " << b3 << endl; system("pause"); return; }
三:函数返回值涉及引用
(一)当函数返回值为引用(局部变量的引用)
int& getRef() { int a = 10; cout << &a << endl; return a; //这是局部变量,一般会在函数结束后被释放栈空间 //但是若是返回的类型是引用,则会将该变量保留 <<重点>> //类似其他语言中,只有当该内存空间无变量指向时,才会被回收 <<重点>> //但是返回引用,则说明,将有其他变量指向该内存空间,不允许回收,延长了生命周期 <<重点>> }
void main() { int a = getRef(); //相当于直接传值出来 cout << &a << " " << a << endl; int &b = getRef(); //将b指向局部变量a的地址,延长了变量生命周期 //注意使用引用来接收int &b,那么该函数返回类型必须是引用int& getRef cout << &b << " " << b << endl; system("pause"); return; }
(二)当函数返回值为引用(static变量的引用)
由于static变量的生命周期是当前文件,故不局限于某个函数。
---既可以作为其他引用的初始值,还可以作为左值进行使用
int& getRef() { static int a = 10; cout << &a << endl; return a; } void main() { int &b = getRef(); //将b指向局部变量a的地址,延长了变量生命周期 cout << &b << " " << b << endl; getRef() = 15; //允许作为左值使用 cout << &b << " " << b << endl; system("pause"); return; }
(三)当函数返回值为引用(返回值是形参) //相当于(一)局部变量,这里用于连接内存和引用
引用归根到底还是对内存的新标识
int& g2(int* p) { *p = 100; cout << p << endl; return *p; //看返回的是一个值,实际该值存放的内存还是和a1内存是一致的,返回的引用地址也就是这个内存地址 } void main() { int a1 = 101; cout << &a1 << " " << a1 << endl; int& a2 = g2(&a1); //a2指向返回的内存地址引用 cout << &a2 << " " << a2 << endl; system("pause"); return; }
(四)当函数返回值为引用(对象的引用,涉及拷贝构造函数和=操作符重载)---需要补充
四:常引用const
(一)使用变量初始化const引用---会将该 引用变量 变为只读
正常使用
尝试修改局部变量
尝试修改引用变量
(二)常用在为他人提供接口,同C++回顾day01---<const常量重点>
设置变量内存为只读,不允许使用接口的用户进行数据修改,只可以进行数据读取
void ReadOnly(const int& a) { cout << &a << " " << a << endl; //a = 110; //不允许修改 } void main() { int a1 = 100; ReadOnly(a1); a1 = 101; ReadOnly(a1); }
四:匿名对象引用(重点:https://www.cnblogs.com/ssyfj/p/10627359.html)
class Test { private: int a, b; public: Test(int a, int b) { this->a = a; this->b = b; } void getInfo() { cout << a << " " << b << endl; } }; Test func1() { return Test(1, 2); //匿名对象1 } void main() { Test T = func1(); //直接将匿名对象用来初始化同类型对象 //会直接将匿名对象设置为这个新的对象 //即匿名对象1没有释放,而是直接变为T对象 cout << &T << endl; T.getInfo(); system("pause"); }
Test& func2() { return Test(3, 4); //匿名对象2 } void main() { Test T = func2(); //使用匿名对象来初始化,会直接将匿名对象转变为这个对象T,延长生命周期 T.getInfo(); Test& T2 = func2(); //若是这里T2是一个引用,则不是直接拷贝赋值, //而是对匿名对象2的内存空间的一个别名, //而这个对象已经被释放了,故结果是随机值 T2.getInfo(); system("pause"); }