我读了很多关于指针和引用的内容,它们仍然让我感到困惑,但我认为这只是一个编程的问题,以获得更好的理解,因为我一周前才开始使用 C++。我一直想知道的一件事是,引用如何知道指向何处?还是对指针的引用?因为引用也必须指向内存中的某个地方,对吗?
我也在堆栈溢出上看到,通常尽可能使用引用。但是如果我查看 hl2 的源代码,很多时候都会使用指针。最后,你们花了多长时间才对何时使用指针和何时不使用指针有良好的感觉?
您可以将引用视为无法更改或获取其值的指针。至于它们和指针之间的区别,最大的区别是你可以在指针上做指针数学,引用只指向单个对象,永远不会改变。
为了一点直觉,如果你要把一个大对象传递给一个函数或方法并且不想复制它(我们现在不考虑移动构造函数),你可以只传递一个 const 引用。方法中的语法就像您传递对象而不复制一样,即使您使用的名称仍将引用原始对象。引用的另一个好处是它们永远不会为空 - 它们将始终引用某些内容,即使该内容可能是回收的内存。
但是,如果您有一个内存块,其中大量对象一个接一个地存储,则可以使用指向该内存开头的指针,使用它,然后将其递增 1 以到达下一个对象。
引用是伪装的指针,它的目标在其生存期的一开始就初始化了。换句话说:
int a = 2;
int& ra = a;
ra = ra + 2;
相当于
int a = 2;
int* pa = &a;
*pa = *pa + 2;
但是参考版本在语法上更容易,并且从根本上无法引用null
- 没有空引用,也没有办法ra
"指向"其他内容。
这类似于询问指针如何知道指向何处,或者整数如何知道要有多大,或者变量名称如何知道它是哪个变量。
编写编译器的人选择如何使这些东西的行为方式与标准所说的行为方式相同。一般来说,在细节深处的某个地方,引用要么"是"变量名,要么"是"指针,这取决于它的初始化方式。
所以,如果你写:
int a = 1;
int &b = a;
然后,编译器实际上可能会在其符号表中注意到,在此作用域中,b
和 a
是同一对象的两个名称。
如果你写:
void foo(int &a) { a = 1; }
然后,编译器使用的调用约定可能会规定此函数的参数的传递方式与采用指针的函数完全相同。函数在拥有参数后对参数执行的操作略有不同。
当然,在后一种情况下,这并不意味着引用"是"程序员的指针。只是编译器编写者在某处使用指针来表示引用。
引用只是变量或对象的别名。它"引用"了它所引用的变量/对象。
int a = 5;
int &x = a;
x 和 a 引用相同的变量。