What is reference?
reference 和 pointer 功能差不多,但语法简单,本质就是一个别名(alias), 是之前存在的一个object的代理,对reference做的事情相当于直接作用于对被引用对象。
Creating reference
规定:reference的命名是前置一个r
int &rSomeRef = someInt;
reference必须初始化,否则编译器报错。
区分:
声明中,&代表引用,*代表指针
语句中,&代表区地址,*代表乘法
Using the Address of Operator on References
Again, 引用是一个别名,对应用取地址,返回的是被引用对象的地址。
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int age = 8;
int &rAge = age;
std::cout << "address of age is " << &age << std::endl;
std::cout << "address of rAge is " << &rAge << std:: endl;
return a.exec();
}
对引用和被引用对象取地址返回同一地址。
#include <QCoreApplication>
#include <iostream>
int main(int argc, char *argv[])
{
using namespace std::endl;
QCoreApplication a(argc, argv);
int age = 88;
int &rAge = age;
int tall = 170;
rAge = tall;//not what you think!
return a.exec();
}
蓝色部分程序员本意可能想,让rAge成为tall的引用,然而,引用只能在创建的时候初始化,其余时间就一直充当引用的作用,也就是说,这句相当于把tall的值赋值给age。
这个语句等价于: age = tall;
What can be referrenced?
可以引用的是OBJECT
不能引用的是CLASS/TYPE
可以有空指针,不可以有空引用
Passing function arguments by references
之前学习的函数有两个缺点:
- 通过值传递(只是copy到了子函数)
- 只有一个返回值
通过引用传递可以规避这两个缺点。


1 #include <QCoreApplication> 2 #include <iostream> 3 4 void swap(int *pX, int *pY); 5 6 int main(int argc, char *argv[]) 7 { 8 QCoreApplication a(argc, argv); 9 int x = 5, y = 10; 10 std::cout << "the value before swap is \nx = " 11 << x << "\ny = " << y << std::endl; 12 swap(&x, &y); 13 14 std::cout << "the value after swap is \nx = " 15 << x << "\ny = " << y << std::endl; 16 17 18 return a.exec(); 19 } 20 21 void swap(int *pX, int *pY) 22 { 23 //display the value befroe swap 24 std::cout << "the value before swap is:\n*pX = " 25 << *pX << "\n*pY = " << *pY << std::endl; 26 int temp = *pX; 27 *pX = *pY; 28 *pY = temp; 29 //display the value after swap 30 std::cout << "the value after swap is:\n*pX = " 31 << *pX << "\n*pY = " << *pY << std::endl; 32 33 }
指针传递虽然能实现两数据交换,但是频繁的进行反引用容易出现错误;调用这个函数要用取地址,封装性不好
C++的目标就是让你只关心这玩意儿是干什么的,返回的是什么。通过指针传递参数,让主调函数很烦啊,打个&&累死人,不小心忘了还容易
下面演示一下引用大法好,直接把刚刚的问题全部解决掉。核心 void swap(&rX, &rY);


1 #include <QCoreApplication> 2 #include <iostream> 3 4 void swap(int &rX, int &rY); 5 6 int main(int argc, char *argv[]) 7 { 8 QCoreApplication a(argc, argv); 9 int x = 5, y = 10; 10 std::cout << "the value before swap is \nx = " 11 << x << "\ny = " << y << std::endl; 12 swap(x, y); 13 14 std::cout << "the value after swap is \nx = " 15 << x << "\ny = " << y << std::endl; 16 17 18 return a.exec(); 19 } 20 21 void swap(int &rX, int &rY) 22 { 23 //display the value befroe swap 24 std::cout << "the value before swap is:\n*pX = " 25 << rX << "\n*pY = " << rY << std::endl; 26 int temp = rX; 27 rX = rY; 28 rY = temp; 29 //display the value after swap 30 std::cout << "the value after swap is:\n*pX = " 31 << rX << "\n*pY = " << rY << std::endl; 32 33 }
对比一下这两个程序的第12行,对主调函数来说,不用去concern太多,这才是好函数
函数通过引用返回多个返回值
1 #include <QCoreApplication> 2 #include <iostream> 3 4 enum ERR_CODE {SUCCESS, ERROR}; 5 ERR_CODE factor(int n, int&rSquared, int&rCubed); 6 //number 采用传值,其目的是防止函数修改number 7 8 int main(int argc, char *argv[]) 9 { 10 QCoreApplication a(argc, argv); 11 12 int number, squared, cubed; 13 ERR_CODE result; 14 15 std::cout << "Enter a number(0-20): "; 16 std::cin >> number; 17 18 result = factor(number, squared, cubed); 19 20 if (result == SUCCESS) 21 { 22 std::cout << "number = " << number << std::endl; 23 std::cout << "squared = " << squared << std::endl; 24 std::cout << "cubed = " << cubed << std::endl; 25 } 26 else 27 { 28 std::cout << "Error encountered!" << std::endl; 29 } 30 31 return a.exec(); 32 } 33 34 ERR_CODE factor(int n, int &rSquared, int &rCubed) 35 { 36 if(n > 20) 37 { 38 return ERROR; 39 } 40 else 41 { 42 rSquared = n * n; 43 rCubed = n * n * n; 44 return SUCCESS; 45 } 46 }
这里的枚举类型的使用应该学习一下,使得程序更加的易读。另外,函数的设计思想也要学习,这里进入函数后首先判断传入参数是否合法,返回值不是客户想要的数值,而是flag,用户的值通过引用直接赋值了。讲究。
Q&A
Q. 既然有了指针了,为何要用引用?
A. 引用不需要用户频繁的去dereference,用指针的玩家===*pNumber = 99; , 用引用的玩家 rNumber = 99;
Q. 你说引用大法好,为什么要有指针?
A. 引用不可以重新赋值,引用不可以为NULL,指针提供灵活的使用方法,就是有点儿费劲。
Q. 传值的方法好处是啥?
A. which prevents the function from changing the original value