一、引用
1.引用的概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内
存空间,它和它引用的变量共用同一块内存空间。
就像李逵的绰号叫黑旋风是一样的,黑旋风其实只是对李逵的引用,指的都是李逵
类型& 引用名 = 被引用
引用一开始,其实是为了取代指针而诞生的,但是改革的并不彻底,无法彻底取代指针
引用的本质,就是取了个别名
引用,一个变量可以有多个引用,同时从语法逻辑来看,引用也并没有开辟新的空间
int main(){ //一个变量可以有多个引用 int a = 0; int& b = a; int& c = b; //引用必须指明,引用对象 int&d;//这样写是错误的 int x = 10; int c = x;//将x的值赋给c,c依旧是a/b的别名 return 0; }
2 引用特性
1. 引用在定义时必须初始化
2. 一个变量可以有多个引用
3. 引用一旦引用一个实体,再不能引用其他实体
3.引用的作用
①、做参数
输出型参数,传参的效率极快
void Swap(int& left,int& right){ int temp = left; left = right; right = temp; }typedef struct ListNode { int val; struct ListNode* next; }*PTNode; void LTPushBack(PTNode& phead, int x); int main(){ return 0; }
②、做返回值
int& Count(){ static int n = 0; n++; // ... return n; }
注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用
引用返回,如果已经还给系统了,则必须使用传值返回。
③、传值、传引用效率比较
传引用返回极大的提高了,时间效率,基本任何场景都可以用引用传参,谨慎用引用做返回
值,出了函数作用域,对象不在了,不能用引用返回,如果还在,可以用引用返回
以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效
率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
#include <time.h>struct A{ int a[10000]; };void TestFunc1(A a){}void TestFunc2(A& a){}void TestRefAndValue(){ A a; // 以值作为函数参数 size_t begin1 = clock(); for (size_t i = 0; i < 10000; ++i) TestFunc1(a); size_t end1 = clock(); // 以引用作为函数参数 size_t begin2 = clock(); for (size_t i = 0; i < 10000; ++i) TestFunc2(a); size_t end2 = clock();// 分别计算两个函数运行结束后的时间 cout << "TestFunc1(A)-time:" << end1 - begin1 << endl; cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
④、值和引用的作为返回值类型的性能比较
#include <time.h>struct A{ int a[10000]; }; A a;// 值返回A TestFunc1() { return a;}// 引用返回A& TestFunc2(){ return a;}void TestReturnByRefOrValue(){ // 以值作为函数的返回值类型 size_t begin1 = clock(); for (size_t i = 0; i < 100000; ++i) TestFunc1(); size_t end1 = clock(); // 以引用作为函数的返回值类型 size_t begin2 = clock(); for (size_t i = 0; i < 100000; ++i) TestFunc2(); size_t end2 = clock(); // 计算两个函数运算完成之后的时间 cout << "TestFunc1 time:" << end1 - begin1 << endl; cout << "TestFunc2 time:" << end2 - begin2 << endl; }
通过上述代码的比较,发现传值和指针在作为传参以及返回值类型上效率相差很大。