一:引用概念---引用就是为一个变量起一个别名
每个变量都是指向一块内存空间的标识,引用就是重新设置一个标识,但是这个标识还是指向同一个内存空间

和指针类似(其实引用本质就是使用了一个常指针 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 = , b1 = ;
int a2 = , b2 = ;
int a3 = , b3 = ;
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 = ;
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 = ;
cout << p << endl;
return *p; //看返回的是一个值,实际该值存放的内存还是和a1内存是一致的,返回的引用地址也就是这个内存地址
}
void main()
{
int a1 = ;
cout << &a1 << " " << a1 << endl;
int& a2 = g2(&a1); //a2指向返回的内存地址引用
cout << &a2 << " " << a2 << endl;
system("pause");
return;
}

(四)当函数返回值为引用(对象的引用,涉及拷贝构造函数和=操作符重载)---需要补充
四:常引用const
(一)使用变量初始化const引用---会将该 引用变量 变为只读
正常使用

尝试修改局部变量

尝试修改引用变量

设置变量内存为只读,不允许使用接口的用户进行数据修改,只可以进行数据读取
void ReadOnly(const int& a)
{
cout << &a << " " << a << endl;
//a = 110; //不允许修改
}
void main()
{
int a1 = ;
ReadOnly(a1);
a1 = ;
ReadOnly(a1);
}


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
}
void main()
{
Test T = func1(); //直接将匿名对象用来初始化同类型对象
//会直接将匿名对象设置为这个新的对象
//即匿名对象1没有释放,而是直接变为T对象
cout << &T << endl;
T.getInfo();
system("pause");
}

Test& func2()
{
return Test(, ); //匿名对象2
}
void main()
{
Test T = func2(); //使用匿名对象来初始化,会直接将匿名对象转变为这个对象T,延长生命周期
T.getInfo();
Test& T2 = func2(); //若是这里T2是一个引用,则不是直接拷贝赋值,
//而是对匿名对象2的内存空间的一个别名,
//而这个对象已经被释放了,故结果是随机值
T2.getInfo();
system("pause");
}
