指针变量和引用变量之间的区别是什么?
当前回答
引用不是给某些内存的另一个名称。它是一个不可变的指针,在使用时会自动取消引用。基本上归结为:
int& j = i;
它内部变成
int* const j = &i;
其他回答
不同之处在于,非常量指针变量(不要与指向常量的指针混淆)可能会在程序执行过程中的某个时间发生更改,需要使用指针语义(&,*)运算符,而引用只能在初始化时设置(这就是为什么您只能在构造函数初始化器列表中设置它们,但不能以其他方式设置它们),并使用普通值访问语义。基本上,引用是为了支持运算符重载而引入的,正如我在一些非常古老的书中所读到的那样。正如有人在这个线程中所说的,指针可以设置为0或任何您想要的值。0(NULL,nullptr)表示指针初始化为空。取消引用空指针是错误的。但实际上,指针可能包含一个不指向某个正确内存位置的值。反过来,引用试图不允许用户初始化对某个无法引用的对象的引用,因为您总是向其提供正确类型的右值。尽管有很多方法可以将引用变量初始化到错误的内存位置,但最好不要深入了解细节。在机器级,指针和参考都通过指针统一工作。让我们假设在基本参考中是句法糖。rvalue引用与此不同,它们自然是堆栈/堆对象。
不能像指针一样取消引用,当取消引用时,
引用和指针都是通过地址工作的。。。
so
你可以这样做
int*val=0xDEADBEEF;*val是0xDEADBEEF的值。
你不能这样做int&V=1;
*不允许使用val。
引用的另一个有趣用法是提供用户定义类型的默认参数:
class UDT
{
public:
UDT() : val_d(33) {};
UDT(int val) : val_d(val) {};
virtual ~UDT() {};
private:
int val_d;
};
class UDT_Derived : public UDT
{
public:
UDT_Derived() : UDT() {};
virtual ~UDT_Derived() {};
};
class Behavior
{
public:
Behavior(
const UDT &udt = UDT()
) {};
};
int main()
{
Behavior b; // take default
UDT u(88);
Behavior c(u);
UDT_Derived ud;
Behavior d(ud);
return 1;
}
默认风格使用引用的“bind const reference to a temporary”方面。
如果你真的想变得迂腐,有一件事你可以用指针做,但不能用指针做:延长临时对象的生命周期。在C++中,如果将常量引用绑定到临时对象,则该对象的生存期将变为引用的生存期。
std::string s1 = "123";
std::string s2 = "456";
std::string s3_copy = s1 + s2;
const std::string& s3_reference = s1 + s2;
在本例中,s3_copy复制连接后的临时对象。而s3_reference本质上成为临时对象。它实际上是对临时对象的引用,该对象现在与引用具有相同的生存期。
如果您尝试在没有常量的情况下执行此操作,它将无法编译。不能将非常量引用绑定到临时对象,也不能为此获取其地址。
也许一些隐喻会有所帮助;在桌面屏幕空间中-
引用要求您指定实际窗口。指针需要屏幕上一块空间的位置,确保它将包含该窗口类型的零个或多个实例。