C++ “引用”究竟是什么?(代码实测)

        C++的引用是个挺好用的东西,相当于指针的另一种写法,虽然引用有一些约束,比如必须初始化而且不能修改引用目标,但确实非常大地增加了编程的清晰度和灵活性。

        引用主要有这些价值:

  1. 简化指针访问,“.”比“->”少一个字符,而且更容易理解
  2. 使指向指针的指针更容易理解,“int * &”比“int **”容易理解多了
  3. 函数传参和重构灵活,可以通过重新定义参数来轻易地在指针和引用之间转换,避免对整个代码进行“.”和“->”的替换。

        当然,凡事有利就有弊,引用本质是个指针,那么就是两个本质相同的东西拥有不同的表达方式,必然会带来一点混乱。

        比如一个以前是“int”类型的参数,现在被改成了“int &”并且在函数里面修改了值,那么原来的程序会出错,而编译器不会发现任何问题。当然,严格地说,这是函数修改者的错误,这种改变接口的行为的变更是不可以轻易进行的,可是事实却是调用者的代码无辜出错了。

        以上是理论,现在我们用代码看看引用到底是什么:

#include 
#include 

void f(int& x)
{
	printf("-------------------------------\n");
	printf("sizeof(x)         : %2zd : typeid : %s\n", sizeof(x), typeid(x).name());
	printf("%p %d\n", &x, x);
}
void f2(int* x)
{
	printf("-------------------------------\n");
	printf("sizeof(x)         : %2zd : typeid : %s\n", sizeof(x), typeid(x).name());
	printf("%p %p\n", &x, x);
}
int main()
{
	int a = 111;
	printf("a   %p %d\n", &a, a);
	int& r_a = a;
	printf("r_a %p %d\n", &r_a, r_a);
	int* p_a = &a;
	printf("p_a %p %p\n", &p_a, p_a);
	
	f(a);
	f(r_a);
    f(*p_a);
	f2(&a);
	f2(&r_a);
	f2(p_a);
	return 0;
}

        这是VS2022的64位C++控制台程序代码(debug版),在main函数任何一处设置断点,调试运行,在程序运行到断点处停下来之后,打开反汇编窗口,看看反汇编代码的样子:

C++ “引用”究竟是什么?(代码实测)_第1张图片

        两个红色方框出的代码分别是给引用和指针赋值,即使完全不懂汇编也能看出来——毫无区别。

        下面是调用"f(int&x)"的反汇编代码:

C++ “引用”究竟是什么?(代码实测)_第2张图片

        “f(r_a)”和“f(*p_a)”的汇编代码相同是能看出来的。

        下面是调用“f2(int* x)”的反汇编代码:

C++ “引用”究竟是什么?(代码实测)_第3张图片

        看得出来,跟前面的一样啊,这就很明白了,“引用”其实就是“指针”,不过语法上被当作“别名”,我们看一下这个程序的输出:

C++ “引用”究竟是什么?(代码实测)_第4张图片

        红线指向的就是“f(int &x)”的参数类型,分明写着“int”啊,所以“引用”在语法层面是“别名”,内部实现为指针。

(这里是结束)

你可能感兴趣的:(软件开发,c++,开发语言,引用)