指针变量和引用变量之间的区别是什么?
当前回答
如果你真的想变得迂腐,有一件事你可以用指针做,但不能用指针做:延长临时对象的生命周期。在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本质上成为临时对象。它实际上是对临时对象的引用,该对象现在与引用具有相同的生存期。
如果您尝试在没有常量的情况下执行此操作,它将无法编译。不能将非常量引用绑定到临时对象,也不能为此获取其地址。
其他回答
如果遵循传递给函数的参数的约定,则可以使用引用和指针之间的差异。Const引用用于传递到函数中的数据,指针用于传递出函数的数据。在其他语言中,您可以使用诸如In和out之类的关键字来明确表示这一点。在C++中,您可以(按照约定)声明等价的。例如
void DoSomething(const Foo& thisIsAnInput, Foo* thisIsAnOutput)
{
if (thisIsAnOuput)
*thisIsAnOutput = thisIsAnInput;
}
使用引用作为输入和指针作为输出是Google风格指南的一部分。
另一个区别是,可以有指向void类型的指针(这意味着指向任何对象的指针),但禁止引用void。
int a;
void * p = &a; // ok
void & p = a; // forbidden
我不能说我真的很满意这种特殊的差异。我更希望它能被允许有意义地引用任何有地址的东西,否则引用行为相同。它将允许使用引用定义一些C库函数的等价物,如memcpy。
此外,作为内联函数的参数的引用的处理方式可能与指针不同。
void increment(int *ptrint) { (*ptrint)++; }
void increment(int &refint) { refint++; }
void incptrtest()
{
int testptr=0;
increment(&testptr);
}
void increftest()
{
int testref=0;
increment(testref);
}
许多编译器在内联指针版本1时实际上会强制写入内存(我们显式地获取地址)。然而,他们会将引用保留在更优化的寄存器中。
当然,对于未内联的函数,指针和引用生成相同的代码,如果函数未修改和返回内部函数,则通过值传递内部函数总是比通过引用传递内部函数更好。
这是基于教程。所写内容更清楚:
>>> The address that locates a variable within memory is
what we call a reference to that variable. (5th paragraph at page 63)
>>> The variable that stores the reference to another
variable is what we call a pointer. (3rd paragraph at page 64)
简单地记住,
>>> reference stands for memory location
>>> pointer is a reference container (Maybe because we will use it for
several times, it is better to remember that reference.)
此外,我们可以参考几乎任何指针教程,指针是指针算术支持的对象,它使指针类似于数组。
看看下面的陈述,
int Tom(0);
int & alias_Tom = Tom;
alias_Tom可以理解为变量的别名(与typedef不同,typedef是一种类型的别名)Tom。忘记这种说法的术语也是可以的,即创建一个对汤姆的引用。
关于引用和指针的一些关键相关细节
指针
使用一元后缀声明符运算符声明指针变量*指针对象被分配一个地址值,例如,通过分配给数组对象、使用一元前缀运算符的对象地址或分配给另一个指针对象的值指针可以重新分配任意次数,指向不同的对象指针是保存指定地址的变量。它占用的内存存储量等于目标机器体系结构的地址大小例如,可以通过增量或加法运算符对指针进行数学操作。因此,可以使用指针等进行迭代。要获取或设置指针引用的对象的内容,必须使用一元前缀运算符*来取消引用它
工具书类
引用在声明时必须初始化。引用使用一元后缀声明符运算符&声明。初始化引用时,可以使用它们将直接引用的对象的名称,而不需要一元前缀运算符&一旦初始化,引用就不能通过赋值或算术操作指向其他对象无需取消引用该引用以获取或设置其引用的对象的内容对引用的赋值操作操作它指向的对象的内容(初始化后),而不是引用本身(不改变它指向的位置)对引用的算术运算操作它指向的对象的内容,而不是引用本身(不会改变它指向的位置)在几乎所有的实现中,引用实际上都存储为被引用对象的内存中的地址。因此,它占用的内存大小与目标机器体系结构的地址大小相同,就像指针对象一样
尽管指针和引用的实现方式几乎相同,但编译器对它们的处理方式不同,导致了上述所有差异。
文章
我最近写的一篇文章比我在这里展示的要详细得多,对这个问题非常有帮助,特别是关于记忆中的事情是如何发生的:
数组、指针和引擎罩下的引用深度文章