这节主要讲指针和引用的区别
指针
c++ 里面的指针和c语言完全一样。
理解指针需要理解地址和值的区别。 T*
就表示到类型 T
的地址,例如:
#include <iostream>
using namespace std;
int main(){
char c = 'a';
char *p = &c;// p 保存着 c的地址
printf("%x\n",p);// 输出c的地址
printf("c = %c", *p);
}
用图来表示就是
当然给指针赋的初始值一定要是合法的地址, 也就是一定要是合法取得的地址,不能死你随便指定的一个数。
指针对象的间接引用 可以通过 指针前面加 *
获取指针所指向对象的所有访问。也就是说 *p
就等于 p
所指向对象,可以做所指对象的所有事情。
下面我们来看看一些表示
int *pi;// 指向 int 的指针
char ** ppc;// 指向 (指向char指针)的指针
int* ap[15];// 指针数组,每个元素ap[i] 都表示一个指向int的指针
int (*fp)(char*);//函数的指针,这种函数以char* 为参数,int为返回值
int* f(char*); // 一个函数,以char*为参数,int*为返回值
如果你理解上面的内容,可以说你就理解指针了,考试也考不了你了。
引用
引用比较复杂,我们重点注意他与指针的区别。
下面的内容摘自 C++之父写的《C++程序设计语言》
一个引用就是一个对象的别名 (表示同一个对象), 主要是为了描述函数的参数和返回值, 既然是别名就必须对其初始化,使其总能引用一个合法名字(总能表示一个合法对象),运行下面的代码,观察编译器的 error
#include <iostream>
using namespace std;
int main(){
int i =0;
int & r = i;// 引用 i,r与i表示同一个对象
int &r0;// 出错必须初始化
r++;// 其实是对 i ++;
int *p = &r;//现在p也指向i;
cout << "r = " << r <<" \n"
<< "i = " << i << "\n"
<< " *p = " << (*p) <<"\n";
}
你完全可以这样来理解引用:
但要记住引用不是一个对象,你不能像指针一样操作他,更多的时候你应该将他理解为名字,名字有什么好处?很大的好处就是节省内存,也就是说在传参数的时候如果参数是个对象,那传引用能节省很大的内存空间。
常引用
引用的初始值必须是一个左值(一个对象,你能得到他的地址),而常引用const T &
不必是左值,甚至可以不是类型 T.
double & dr = 10;//编译错误
const double & cdr = 10;//ok
你可以这样理解常引用,他先创建一个临时变量,然后将其转化为一个引用。
double tmp = double(10);//强制类型转化为一个临时变量
const double & cdr = &tmp;
引用作为函数参数
这个最大的优势是减少内存开销,还有就是能获得参数的原始对象,而不是copy对象,如交换函数 swap
。不过推荐的方式是使用常引用作为参数。
#include <iostream>
using namespace std;
void swap(int & a,int & b){
int tmp = a;
a = b;
b = tmp;
}
int main(){
int a = 1,b = 2;
swap(a,b);
cout << a <<" " << b<<"\n";
}
引用作为返回值
引用作为返回值最大的优势在于可以赋值给他,也就是函数作为赋值对象,后续函数重载会用到
#include <iostream>
using namespace std;
int arr[10];
int& set_val(int idx){
return arr[idx];
}
int main(){
for(int i=0 ; i< sizeof(arr)/sizeof(arr[0]) ; ++i)
arr[i] =0;
set_val(3) = 1;
for(int i=0 ; i< sizeof(arr)/sizeof(arr[0]) ; ++i)
cout <<arr[i] <<" ";
}