C++ 引用



C++ 中的引用

引用的本质其实就是const指针,C++编译器在编译过程中使用使用常量指针作为引用的内部实现,因此引用所占的空间与指针相同。

而从使用者的角度来看,引用只是一个别名,它和原变量一样使用,而且它简单易用,可以避免操作指引带来的问题。

int main()
{ 
    int y=10;
    int &r = y;  // r是y的引用
    cout << r;
}

以上实例输出结果:

10


引用和指针的区别

引用指针
引用必须在声明的时候就初始化指针可以在任何时候初始化
只能初始化一次可以被初始化无数次
不能有空引用指针可以置为空
引用无需解引用指针用*号解引用

函数中的引用

引用通常用于函数参数列表和函数返回值,和指针一样。

在函数中使用引用的规则

  1. 当我们在参数列表中使用引用时,必须要注意,函数内部对引用的任何更改都会导致函数外部原始参数的更改。
  2. 当我们函数的返回值是引用时,你应该注意引用的变量的生命周期,如果是在函数内部声明的变量,一旦函数结束,这个引用将无效,而globalstatic则没有这个问题。

举例说明References的使用

下面我们通过一个简单的代码示例来学习 C++ 中引用的使用


int* first (int* x)
{ 
    (*x++);
    return x;   // 安全,x在外部
}

int& second (int& x)
{ 
    x++;
    return x;   // 安全,x在外部
}

int& third ()
{ 
    int q;
    return q;   // 错误,函数结束时q的生命周期也跟着结束
}

int& fourth ()
{ 
    static int x;
    return x;   // 安全,x是静态变量,因此它的生命周期一直存在
}

我们在上面的程序中有四个不同的函数。

  • first() 将指针作为参数并返回一个指针,它可以正常工作,返回的指针指向在 first() 之外声明的变量,因此即使在 first() 结束后它仍然有效。
  • 同样,second() 也可以正常工作,返回的引用是从外部传入的,它不会随着函数结束而结束。
  • 但是在 third() 的情况下,我们在函数内部声明一个变量 q 并尝试返回一个它的引用,但是一旦函数 third() 结束,局部变量 q 就会被销毁,因此什么也没有返回。
  • 为了解决上述问题,我们在函数 fourth() 中将 x 设为 static,赋予它一个生命周期直到程序结束,因此对x的引用也是有效的。


C++ 中的常量引用

常量引用用于函数参数中,以防止函数更改参数。

void g(const int& x)
{ 
    x++; 
}   // 错误

int main()
{
    int i=10;
    g(i);
}

我们不能更改函数中的参数,因为它是作为 const 引用传递的。



参数传递准则

通常在函数调用时使用 值传递只是为了防止我们的对象或变量被更改或修改,但是每当我们按值传递参数时,它的新副本就会被创建,如果我们将对象作为参数传递,那么会创建该对象的副本(调用构造函数和析构函数),这会影响效率。

因此,我们必须使用 const引用 类型的参数,当我们使用 const 引用时,只有一个地址在堆栈上传递,该地址在函数内部使用,并且函数不能更改我们的参数,因为它是 const 类型。

因此使用 const 引用类型参数即可以减少开销,又可以避免我们的参数被更改,这也是有经验的程序员经常使用的方法。