1、引用的定义和使用

#include <iostream>

int main()
{
    int x = 10;
    int& a = x;
    int& b = x;
    a = 11;
    b = 12;
    std::cout << x << std::endl;//12
    std::cout << a << std::endl;//12
    std::cout << b << std::endl;//12
    std::cout << "Hello World!\n";
}

语法是:类型& 变量名=值

  • a、b都是x的引用,是x的别名。
    对a、b、x任一的修改都是修改同一个地址的值,即变量x的值。
  • 创建引用变量a、b时,必须赋值(初始化)。
  • a、b初始化后,永远是x的引用,无法再改变为其他变量的引用。
  • 不存在NULL引用。一定是具有合法地址的变量的引用。

2、引用的本质

本质是指针。只是编译器层面的语法处理,编译后会变成指针的写法。

int x = 1;
int& a = x;//编译器处理为:int * const aref = &x;
a = 10;//编译器处理为:*aref = 10;
//其中aref是编译器起的名字,用户不可知。

本质是处理成指针常量/常指针。就是指向初始化后不能改变的指针。

所以一个引用在内存中是占用8个字节存储(就是按指针的存储):

#include <iostream>
class Person {
    int& a;
    int& b;
};
int main()
{
    //通过sizeof获取Person数据类型占用的内存空间
    std::cout << sizeof(Person) << std::endl;//16
}

有时编译器会将引用优化掉,完全用所引用的变量,不会额外创建指针常量。

3、引用作为函数参数

#include <iostream>
void add(int& a) {
    a++;
}
int main()
{
    int x = 1;
    add(x);
    std::cout << x << std::endl;//2
}

引用作为函数参数时,相当于传的是实参的指针,也就能在函数中通过改变形参来改变实参的值。

在一些场景代替指针,具有更好的可读性和实用性。

引用的地址

#include <iostream>

int main()
{
    int x = 10;
    int& a = x;
    int& b = x;
    a = 11;
    b = 12;
    std::cout << &x << std::endl;
    std::cout << &a << std::endl;
    std::cout << &b << std::endl;
    std::cout << "Hello World!\n";
}

&获取引用的地址,并不是获得编译器内部分配的指针常量的地址,而是编译器将&a处理为返回所引用的x的地址。
所以&a&x的值相同,都是x的地址。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐