这些是一样的吗:

int foo(bar* p) {
  return p->someInt();
}

int foo(bar& r) {
  return r.someInt();
}

忽略空指针的可能性。这两个函数在功能上是否相同,无论 someInt() 是虚拟的或者如果它们通过了 bar 或一个子类 bar?

这个切片有什么作用吗:

bar& ref = *ptr_to_bar;
有帮助吗?

解决方案

标准中有意未指定使用指针实现的 C++ 引用。引用更像是变量的“同义词”,而不是指向变量的指针。当可能意识到指针在某些情况下会显得过分时,这种语义为编译器提供了一些可能的优化。

还有一些差异:

  • 您不能将 NULL 分配给引用。这是一个至关重要的差异,也是您偏爱另一个的主要原因。
  • 当您获取指针的地址时,您将获得指针变量的地址。当您获取参考的地址时,您将获得所引用的变量的地址。
  • 您无法重新分配参考。一旦它被初始化,它在整个生命周期中都指向同一个对象。

其他提示

忽略每一种语法糖和可以用一个而不是另一个来完成的可能性,以及其他答案(其他问题)中解释的指针和引用之间的差异......是的,这两个在功能上完全相同!两者都可以很好地调用函数并处理虚函数。

不,你的线不会切片。它只是将引用直接绑定到指针指向的对象。

关于为什么要使用其中一种而不是另一种的一些问题:

我不会自己尝试找出差异,而是将您委托给那些您想知道的人。

引用是一个常量指针,即,您无法更改引用以引用其他对象。如果更改,引用对象的值将更改。

对于Ex:

       int j = 10;
       int &i = j;
       int l = 20;
       i = l; // Now value of j = 20

       int *k = &j;
       k = &l;   // Value of j is still 10

我很长时间没有使用过C ++,所以我甚至都不会尝试回答你的问题(对不起);但是,Eric Lippert刚刚发布了一篇优秀文章关于我认为我指向你的指针/参考文献。

是的,它们在功能上是相同的。由于引用需要您在使用它之前将其设置为对象,因此您不必处理空指针或指向无效内存的指针。

查看语义差异也很重要:

  • 当您实际要正常传递对象时,请使用引用 - 但它太大了,因此传递对对象的引用而不是制作副本更有意义(如果您不修改对象)。
  • 当您想要处理内存地址而不是对象时,请使用指针。

不确定是否有人回答了关于切片的隐藏在底部的第二个问题...不会导致切片。

切片是指将派生对象分配(复制)到基类对象时 - 派生类的特化是“切片”的。关闭。请注意,我说复制了对象,我们不是在讨论被复制/分配的指针,而是对象本身。

在你的例子中,那没有发生。您只是取消引用指向Bar对象的指针(从而导致Bar对象)被用作参考初始化中的右值。不确定我的术语是否正确......

正如其他人所提到的,在实现中引用和指针基本上是相同的。有一些小警告:

  • 您无法将null分配给参考(Shoosh提到了这一点):这很重要,因为没有“未定义”或“无效”参考值。

  • 您可以将临时变量作为一个 常量 参考,但是将指针转到临时性是不合法的。

例如,这样就可以了:

class Thingy; // assume a constructor Thingy(int,int)
void foo(const Thingy &a)
{ 
   a.DoSomething();
}

void bar( ) 
{
  foo( Thingy(1,2) );
}

但大多数编译器会抱怨

void foo2( Thingy * a);

void bar2()
{
  foo( &Thingy(1,2) );
}
  • 获取变量的地址来获取指针会强制编译器将其保存到内存中。将引用分配给局部变量只是创建一个同义词;在某些情况下,这可能允许编译器将数据保留在寄存器上并避免 加载-命中-存储. 。然而,这仅适用于局部变量——一旦通过引用将某些内容作为参数传递,就不可避免地将其保存到堆栈中。

 

void foo()
{
   int a = 5;
   // this may be slightly more efficient
   int &b = a;
   printf( "%d", ++b );
   // than this
   int *c = &a;
   printf( "%d", ++(*c) );
}
  • 同样, __限制关键字 不能应用于引用,只能应用于指针。

  • 您无法使用引用进行指针算术,因此,如果您有一个指向数组的指针,则可以通过 p+1 获得数组中的下一个元素,而引用在其整个生命周期中仅指向一件事。

这些功能显然不是“相同的”,但就虚拟行为而言,它们的行为类似。关于切片,这只发生在处理值时,而不是引用或指针。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top