指针变量和引用变量之间的区别是什么?
当前回答
也许一些隐喻会有所帮助;在桌面屏幕空间中-
引用要求您指定实际窗口。指针需要屏幕上一块空间的位置,确保它将包含该窗口类型的零个或多个实例。
其他回答
我总是根据C++核心指南中的这条规则来决定:
当“无参数”是有效选项时,优先选择T*而不是T&
不同之处在于,非常量指针变量(不要与指向常量的指针混淆)可能会在程序执行过程中的某个时间发生更改,需要使用指针语义(&,*)运算符,而引用只能在初始化时设置(这就是为什么您只能在构造函数初始化器列表中设置它们,但不能以其他方式设置它们),并使用普通值访问语义。基本上,引用是为了支持运算符重载而引入的,正如我在一些非常古老的书中所读到的那样。正如有人在这个线程中所说的,指针可以设置为0或任何您想要的值。0(NULL,nullptr)表示指针初始化为空。取消引用空指针是错误的。但实际上,指针可能包含一个不指向某个正确内存位置的值。反过来,引用试图不允许用户初始化对某个无法引用的对象的引用,因为您总是向其提供正确类型的右值。尽管有很多方法可以将引用变量初始化到错误的内存位置,但最好不要深入了解细节。在机器级,指针和参考都通过指针统一工作。让我们假设在基本参考中是句法糖。rvalue引用与此不同,它们自然是堆栈/堆对象。
这个程序可能有助于理解问题的答案。这是一个引用“j”和指向变量“x”的指针“ptr”的简单程序。
#include<iostream>
using namespace std;
int main()
{
int *ptr=0, x=9; // pointer and variable declaration
ptr=&x; // pointer to variable "x"
int & j=x; // reference declaration; reference to variable "x"
cout << "x=" << x << endl;
cout << "&x=" << &x << endl;
cout << "j=" << j << endl;
cout << "&j=" << &j << endl;
cout << "*ptr=" << *ptr << endl;
cout << "ptr=" << ptr << endl;
cout << "&ptr=" << &ptr << endl;
getch();
}
运行程序并查看输出,您就会明白。
另外,抽出10分钟观看以下视频:https://www.youtube.com/watch?v=rlJrrGV0iOg
虽然引用和指针都用于间接访问另一个值,但引用和指针之间有两个重要的区别。第一个是引用总是引用一个对象:在没有初始化引用的情况下定义引用是错误的。赋值行为是第二个重要区别:赋值给引用会更改引用绑定的对象;它不会将引用重新绑定到另一个对象。初始化后,引用始终引用同一基础对象。
考虑这两个程序片段。首先,我们将一个指针分配给另一个指针:
int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2; // pi now points to ival2
在赋值ival之后,pi所寻址的对象保持不变。赋值会更改pi的值,使其指向不同的对象。现在考虑一个分配两个引用的类似程序:
int &ri = ival, &ri2 = ival2;
ri = ri2; // assigns ival2 to ival
此赋值更改了ri引用的值ival,而不是引用本身。赋值后,两个引用仍然引用其原始对象,并且这些对象的值现在也相同。
它占用多少空间并不重要,因为你实际上看不到它占用的任何空间的任何副作用(不执行代码)。
另一方面,引用和指针之间的一个主要区别是,分配给常量引用的临时变量在常量引用超出范围之前一直有效。
例如:
class scope_test
{
public:
~scope_test() { printf("scope_test done!\n"); }
};
...
{
const scope_test &test= scope_test();
printf("in scope\n");
}
将打印:
in scope
scope_test done!
这是允许ScopeGuard工作的语言机制。