《C++ Primer》学习笔记——C++引用

1. 引用是object的别名,它自己本身不是object,而指针变量则是一个object。
2. 引用必须初始化,因为它一旦绑定一个object以后,就不可再与其他object重新绑定了,如下面这个程序:
// ref.cpp
int main(void)
{
    int ival1 = 4;
    int ival2 = 5;
    int &rval1 = ival1;
    int &rval2 = ival2;
    rval1 = rval2;
    return 0;
}
编译程序:
$ g++ -g ref.cpp
使用gdb调试运行出来的程序,设置断点在return前:
(gdb) p &ival1
$1 = (int *) 0x7fffffffe1d8
(gdb) p &ival2
$2 = (int *) 0x7fffffffe1dc
(gdb) p rval1
$3 = (int &) @0x7fffffffe1d8: 5
(gdb) p rval2
$4 = (int &) @0x7fffffffe1dc: 5
(gdb) p ival1
$1 = 5
可以看到执行 rval1 = rval2 以后,引用 rval1 并不像指针一样,改为指向变量 ival2,自始至终都是和 ival1 的地址相同(都是0x7fffffffe1d8,指针变量则会有自己独立的地址),而且这带来的另外一个效果是 ival1 被赋值5。这就是引用“object别名”的意义所在,修改引用,就是修改被其引用的变量。
3. 除了两种特殊情况以外,引用必须和被引用的对象类型完全一致,下面的程序编译时会报错:
int main(void)
{
    int ival = 4;
    double &rval = ival;    // 错误:类型不匹配
    return 0;
}
4. 两种特殊情况的第一种涉及到const:
我们可以对具有const属性的引用,使用任意一个,能够转成被其引用变量类型的表达式,来初始化这个引用(we can initialize a  reference to const from any expression that can be converted to the type of the reference)
对于第3点的例子,原本因为类型不匹配造成的编译错误,只要在double前加上const,
int main(void)
{
    int ival = 4;
    const double &rval = ival;
    return 0;
}
就不会有编译错误出现。
为什么会这样,调试这段程序,同样在return前加断点:
(gdb) p ival
$3 = 4
(gdb) p &ival
$1 = (int *) 0x7fffffffe1dc
(gdb) p rval
$4 = (const double &) @0x7fffffffe1c8: 4
可以看到虽然 ival 和 rval 的值都是4,但是地址却不一样!这与最初的引用就是object的别名似乎有冲突!其实不是这样,《C++ Primer》给出解释(原文是double转int):编译器为了保证引用的对象和引用本身是同一种类型,会将中间那行代码转换为如下的效果:
const double temp  = ival;
const double &rval = temp;
所以rval实际上引用的是一个无名的临时变量(temporary object),这个object有自己的地址空间,但是没法通过变量名来索引。

你可能感兴趣的:(c++,c++,引用)