之前在C语言里面,函数的传引用一直是传地址,于是一直就把引用当作地址了。
现在用C++,发现其实引用并不是地址,原来自己一直理解错了。
下面有一段程序,帮助我们理解:
/** @function main */
int main( int argc, char** argv )
{
int a=10; // int 变量
int &b=a; // 引用
int *c=&a; // 指针
cout<<"b="<<b<<endl;
cout<<"&a="<<&a<<endl;
cout<<"c="<<c<<endl;
cout<<"&b="<<&b<<endl;
return 0;
}
输出:
b=10
&a=0xbfbc0347
c=0xbfbc0347
&b=0xbfbc0347
第一个cout,输出引用b,输出的就是a的结果;所以C++ primer书里面说的:引用就是变量的别名,这句话很贴切。可以理解为:在编译器看来,用b的地方其实就是a,所以我在猜测,在编译器里面,对待引用是否就是将变量替换过来了,应该是这样的。(ps:高手请留言,求拍)
为什么要有引用这个发明呢?引用的主要用处是用在给函数传递参数,这在C++ primer plus这本书里面讲的比较详细。
第二个cout,输出的是a的地址,自然是0xbfbc0347了。
第三个cout,输出指针c,由于指针里面存的数据就是a的地址,所以也是0xbfbc0347。
第四个cout,输出引用b的地址,由于b其实就是a,所以输出的也就是a的地址,所以也是0xbfbc0347。
常引用const:引用的对象是一个常量
初始化常引用时,可以使用任意表达式作为初始值。
/** @function main */
int main( int argc, char** argv )
{
int a=10;
const int &b=10;
const int &c=a;
a=20;
cout<<"b="<<b<<endl;
cout<<"&b="<<&b<<endl;
cout<<"c="<<c<<endl;
cout<<"&c="<<&c<<endl;
return 0;
}
输出:
b=10
&b=0xbfd75e00
c=20
&c=0xbfd75e04
从输出可以看出:常量引用可以初始化为常数10,也可以初始化为普通变量,而且普通变量a的值还可以更改。由于c是常量引用,无法通过c来更改a的值,但是a本身是普通int变量,所以其自身是可以更改的。
临时量对象
/** @function main */
int main( int argc, char** argv )
{
float a=10.12;
const int &b=a;
cout<<"&a="<<&a<<endl;
cout<<"&b="<<&b<<endl;
return 0;
}
输出地址就不是一样的了,可以b并未直接与a绑定,编译器做了手脚:
输出:
&a=0xbfdbfa94
&b=0xbfdbfa98
引用b需要绑定一个int型变量,但是a是float型的,这该怎么办呢?编译器创建了一个临时变量temp,用来将float转换成int,并且将b绑定temp,这个临时变量是一个未命名的对象。
编译器采用的方法,类似下面的代码:
float a=10.12;
const int temp=a;
const int &b=temp;
这个临时变量temp对于程序员来说是透明的,是看不到的。
常指针 vs 指向常量的指针
常指针:指针本身是常量,指针声明时候必须初始化,初始化后值不能再改变
int a=8;
int *const b=&a;
这里b将永远指向a,×b可以更改a 的值。
指向常量的指针:指针指向的对象是常量,不能通过指针改变常量对象的值,但是可以让指针指向其他变量。
const int a=8;
const int *b=&a;
const int c=9;
b=&c;
这里b可以指向a,也可以指向c。