目录
1 引用的基本概念
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
/*
1 引用没有定义,是一种关系型声明。声明它和原有某一变量(实体)的关
系。故 而类型与原类型保持一致,且不分配内存。与被引用的变量有相同的地
址。
2 声明的时候必须初始化,一经声明,不可变更。
3 可对引用,再次引用。多次引用的结果,是某一变量具有多个别名。
4 &符号前有数据类型时,是引用。其它皆为取地址。
*/
int printA(int &a) //引用作为函数参数的时候不需要初始化, 因为形参一定会被赋值的。
{
cout << "a = " << a << endl;
return 0;
}
int main(void)
{
int a = 10; //在内存上开辟4个字节, a就代表这个4个字节内存
int *p = &a; //让一个指针 指向这个4个字节的空间
*p = 20;
cout << "a = " << a << endl;
//c++提供了另一种对 变量的间接操作的方式, 就是使用引用
int & b = a; //定义一个引用b 指向a, b此时就是变量的a的别名
//double &c = a;
b = 40;
cout << "a = " << &a << endl;
cout << "b = " << b << endl;
cout << "&a = " << &a << endl;
cout << "&b =" << &b << endl;
//int & c; //只是单纯定义一个引用, 不初始化, 引用一定要初始化
int &bb = b; //对b引用再次 引用, 实际上是b的别名
cout << "bb = " << bb << endl;
cout << "&bb =" << &bb << endl;
return 0;
}
2 引用作为函数参数的意义
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
struct Teacher
{
int id;
char name[64];
};
void printT(Teacher t) //局部临时变量, 会发生值拷贝
{
cout << "id = " << t.id << endl;
cout << "name = " << t.name << endl;
t.id = 100;
}
void printT2(Teacher *t)
{
cout << "id = " << t->id << endl;
cout << "name = " << t->name << endl;
t->id = 100;
}
void printT3(Teacher &t)//Teacher & t = t1; t 就是t1的一个别名
//在理解引用的时候, 就当变量的别名来理解。
{
cout << "id = " << t.id << endl;
cout << "name = " << t.name << endl;
t.id = 1000;
}
//交换不成功
void my_swap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void my_swap02(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void my_swap03(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
int main(void)
{
Teacher t1 = {1, "zhang3"};
printT(t1);
cout << t1.id << endl;
printT2(&t1);
cout << t1.id << endl;
printT3(t1);
cout << t1.id << endl;
int a = 10;
int b = 20;
my_swap01(a, b);
cout << "a = " << a << ", b = " << b << endl;
my_swap02(&a, &b);
cout << "a = " << a << ", b = " << b << endl;
my_swap03(a, b);
cout << "a = " << a << ", b = " << b << endl;
return 0;
}
3 引用的意义和本质
能给同一块内存空间起不同的别名,a 和b 都是同一块内存空间的门牌号。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
struct TypeA
{
int *a;
};
struct TypeB
{
double &a;
};
struct Teacher
{
int id;
char name[64];
};
void motifyTeacher(Teacher &t) //
{
t.id = 100; // 如果说t是一个常指针, *t 就是指针指向内存空间 (*t).id = 100
//当你要试图修改或者获取已经初始化的引用的时候, 编译器会有一个隐藏的*的操作
}
void motifyA(int *const a) //常指针 也是一个常量, 也是必须要初始化, 也不能被修改
{
*a = 100;
}
void motifyB(int &a)
{
a = 1000; //a 实际上是一个常量指针, 但是如果你给一个a赋值,编译器会有一个隐形的操作, *
}
//在研究引用的时候 ,可以将引用理解为 一个 常指针
//在理解引用的时候, 可以将引用理解为 一个变量的别名
void test()
{
int value = 20;
Teacher t1 = { 1, "zhangsan" };
motifyA(&value);
cout << "value = " << value << endl;
motifyB(value); // int value --> int &a , int& a = value 给引用指定指向哪个变量的时候, 编译器提供又有了一个隐形的操作
// a = &value;
cout << "value = " << value << endl;
motifyTeacher(t1); //如果说 motifyTeacher 的形参是一个常指针,Teacher *const t = &t1;
//编译器发现 Teacher &t 形参是一个引用, Teacher &t = &t1;
//当给引用初始化的时候, 会有一个& 的隐形操作
}
void motifyAA(int *a)
{
*a = 100; //间接的赋值
}
void motifyBB(int &a) //int &a = a; a = &a;
{
a = 200; //*a = 200
}
void test2()
{
int a = 10; //条件一
motifyAA(&a); //int*a = &a; //建立了关联
motifyBB(a);
}
int main(void)
{
int a = 10;
int b = 20;
const int c_a = 10;
//c_a = 20;//常量在初始化之后,不能够再修改了
int &re = a; //引用必须初始化. 引用在初始化之后,也不能够被改变
re = b; // a = b 而不是 让re引用指向b
cout << "re = " << re << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
re = 100; //是该的a 还是b?
cout << "re = " << re << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
//1 引用 可能是一个 常量?
cout << "sizeof(TypeA): " << sizeof(TypeA) << endl;
cout << "sizeof(TypeB):" << sizeof(TypeB) << endl;
//通过对引用求大小, 发现不管引用是什么类型 都是4个字节,都跟指针的大小一样。
//2 引用可能是一个 指针?
test();
return 0;
}
4 引用作为函数返回值
值的返回放在了寄存器
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
int getA1()
{
int a = 10;
return a;
} //value_a = a;
int &getA2()
{
int a = 10;
return a;
} //匿名的引用 int & = a; // int &temp = &a;
int &getBB()
{
static int b = 100;
return b;
}
int main(void)
{
int value_a = 0;
value_a = getA1(); //正确
cout << "value_a " << value_a << endl;
value_a = getA2();// int value_a = temp; // int value_a = *temp; //这是一个值拷贝
cout << "value_a " << value_a << endl;
cout << "value_a " << value_a << endl;
int &r_a = getA2(); //没有值拷贝动作 ,禁止
//当函数返回值,是一个局部变量的引用的时候,不能再用引用来接收。
cout << "r_a " << r_a << endl;
cout << "r_a " << r_a << endl;
int &r_b = getBB(); //此时的r_b 就是 getBB中的 static int b
//当函数返回值,不是子函数内部局部变量,就可以用引用进行接收,
cout << "r_b " << r_b << endl;
cout << "r_b " << r_b << endl;
r_b = 2000; //此时r_b 就是getBB中的b的别名, 修改r_b 就是修改 b
int value_b = getBB(); // 会有一个临时的引用 int &temp = b; value_b = *temp; //发生了值拷贝
//getBB();//getBB 就是b的别名
//int value_b = *(getBB());
//int value_b = static b;
cout << "value_b " << value_b << endl;
getBB() = 3000; //static b = 3000; //当引用作为函数的返回值的时候,只要这个引用是合法的,就可以当左值。
//三目运算符
int a = 10;
int b = 20;
(a < b ? a : b) = 30;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
5 指针的引用
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
struct Teacher
{
int id;
char name[64];
};
int getTeacher(Teacher **pp)
{
Teacher *p = NULL;
p = (Teacher *)malloc(sizeof(Teacher));
if (p == NULL)
{
cout << "error" << endl;
return -1;
}
memset(p, 0, sizeof(Teacher));
p->id = 30;
strcpy(p->name, "zhang3");
*pp = p;
return 0;
}
int getTeacher02(Teacher* &tr) //tr 就是main中的tp
{
tr = (Teacher*)malloc(sizeof(Teacher));
if (tr == NULL) {
cout << "error" << endl;
return -1;
}
tr->id = 40;
strcpy(tr->name, "li4");
return 0;
}
void freeTeacher02(Teacher * &tr)
{
if (tr != NULL) {
free(tr);
tr = NULL;
}
}
void freeTeacher(Teacher **pp)
{
if (pp == NULL) {
return;
}
Teacher *p = *pp;
if (p != NULL) {
free(p);
*pp = NULL;
}
}
int main(void)
{
Teacher *tp = NULL;
//getTeacher(&tp);
getTeacher02(tp);
cout << tp->id << ", " << tp->name << endl;
//freeTeacher(&tp);
freeTeacher02(tp);
return 0;
}
const引用
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//const引用一般用在形参上,来限制 被引用的变量不能被修改,
void printX(const int & re )
{
cout << "re " << re << endl;
}
int main(void)
{
const int a = 10; // a必须初始化
//int & b = a;
const int &b = a;
//如果是一个const 常量, 必须用const 引用来接收它
int x = 3.14;
const int &re1 = x;
cout << "re1 " << re1 << endl;
x = 20;
cout << "re1 " << re1 << ", x: " << x << endl;
const int &re2 = 10;// 用const 引用 引用一个字面量
// 当用一个const 引用 去引用一个字面量的时候, 字面量他是没有地址,
//引用是无法 对字面量取地址的, 临时创建一个 int temp, 10 --->temp
//const int &re2 = temp;
//用re2 就是代表 temp,re2是const的引用,你无法去改变temp的值
//int &re2 = 10; //非常量引用 必须是左值。 左值就是可以放在=左边的表达式,左值是可以赋值,是有内存空间的
//如果想对一个字面量做引用的话,只能用 const 的引用
cout << "re2 = " << re2 << endl;
cout << "sizeof(re2)" << sizeof(re2) << endl;
return 0;
}
const int &m = 13; //right c++ 编译器会分配内存空间