一、概述与定义
先说下变量:变量名实质上是一段连续存储空间的别名,程序中通过变量来申请并命名内存空间,通过变量的名字可以使用存储空间。
引用:在C++中引用可以看作一个已定义变量的别名。
引用的语法: Type& name = var;
int main()
{
int a = 10;
int &b = a;
cout << "b->" << b << endl;
cout << "a->" << a << endl;
cout << "&a->" << &a << endl;
cout << "&b->" << &b << endl;
system("pause");
return 0;
}
输出结果:
二、引用作函数参数
引用作函数参数时也是变量的别名。
#include <iostream>
using namespace std;
struct Student
{
int num;
int age;
};
//引用作函数的参数就是实参的别名
void PrintStu(Student& stu)
{
cout << stu.num << endl;
stu.age = 12;
}
int main()
{
Student stu1;
Student& stu2 = stu1;//必需进行初始化
stu2.num = 1;
stu2.age = 10;
PrintStu(stu1);
cout << stu1.age << endl;
system("pause");
return 0;
}
运行结果:
三、引用的本质
先看下下面的程序:
#include <iostream>
using namespace std;
struct Student {
int &a;
int c;
};
int main()
{
printf("sizeof(Student) %d\n", sizeof(Student));
system("pause");
return 0;
}
运行结果:
这个现象的背后隐藏了多少不为人知的秘密?
引用是一个有地址,引用是常量
引用在C++中的内部实现是一个常指针;Type& name <==>Type* const name。
C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。
从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做出的细节隐藏:当实参传给形参引用的时候,只不过是c++编译器帮我们程序员手工取了一个实参地址,传给了形参引用(常量指针)。
四、引用注意事项
4.1当函数返回值为引用时
若返回栈变量,可能乱码,也可能不乱码。
不能成为其它引用的初始值
不能作为左值使用
#include <iostream>
using namespace std;
int getA()
{
int a = 10;
return a;
}
int& getA2()
{
int a = 10;
return a;
}
int main()
{
int a1 = 0;
int a2 = 0;
a1 = getA();
a2 = getA2();
int &a3 = getA2();//乱码
cout << "a1->" << a1 << endl;
cout << "a2->" << a2 << endl;
cout << "a3->" << a3 << endl;
system("pause");
return 0;
}
运行结果:
4.2若返回静态变量或全局变量
可以成为其他引用的初始值
即可作为右值使用,也可作为左值使用
#include <iostream>
using namespace std;
static int a;
int getA()
{
a = 10;
return a;
}
int& getA2()
{
a = 10;
return a;
}
int main()
{
int a1 = 0;
int a2 = 0;
a1 = getA();
a2 = getA2();
int &a3 = getA2();
cout << "a1->" << a1 << endl;
cout << "a2->" << a2 << endl;
cout << "a3->" << a3 << endl;
system("pause");
return 0;
}
运行结果:
4.3当被 调用的波函数当左值的时候,必须返回一个引用
#include <iostream>
using namespace std;
int& fun()
{
static int a = 10;
a++;
cout << "a->" << a << endl;
return a;
}
//相当于手工打造做左值的条件
int* fun2()
{
static int a = 10;
a++;
cout << "a->" << a << endl;
return &a;
}
int main()
{
fun() = 100;
fun();
*(fun2()) = 200;
fun2();
system("pause");
return 0;
}
运算结果:
4.4结论:
用引用去接收函数的返回值,是不是乱码,关键是看返回 的内存空间是不是被编译器回收了。
五、指针的引用
#include <iostream>
using namespace std;
struct Student
{
char name[50];
int age;
};
int getStu(Student **stu)
{
Student *p1 = (Student*)malloc(sizeof(Student));
if (p1 == NULL)
return -1;
memset(p1, 0, sizeof(Student));
p1->age = 16;
*stu = p1;
return 0;
}
int getStu2(Student* &stu)
{
stu = (Student*)malloc(sizeof(Student));
stu->age = 16;
return 0;
}
int main()
{
Student *p = NULL;
getStu2(p);//与getStu(&p); 相当
system("pause");
return 0;
}
六、const引用
分两种情况:
6.1用变量对const引用初始化
const引用让变量所只内存空间拥有只读属性,这种用途用得比较多的有作波函数的形参
int a = 10;
const int &b = a;
a=11;//正确
b=11;//错误
6.2用常量对const引用初始化
#include <iostream>
using namespace std;
int main()
{
const int &a = 10; //去掉const编译不通过
int *p = (int *)&a; //注意需要(int *)
*p = 12;
printf("a:%d", a);
system("pause");
return 0;
}
当使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名,使用常量对const引用初始化后将生成一个只读变量。
另外,const引用都可以通过指针支修改变量的值。这区别于我的另外一篇博客,c/c++中的const。