指针和参考参数之间的区别?

时间:2009-03-06 22:05:14

标签: c++ pointers reference object-slicing

这些是否相同:

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

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

忽略空指针潜力。这两个函数在功能上是否相同,无论someInt()是虚拟的还是传递barbar的子类?

这会切片吗:

bar& ref = *ptr_to_bar;

8 个答案:

答案 0 :(得分:64)

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

还有一些差异:

  • 您不能为引用分配NULL。 这是一个至关重要的区别 你更喜欢一个人的主要原因 其他。
  • 当你拿一个地址时 指针,你得到的地址 指针变量。当你拿走 参考地址,你得到了 变量的地址 提到。
  • 您无法重新分配参考。一旦它被初始化,它就会指向同一个物体。

答案 1 :(得分:14)

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

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

关于你为什么要使用其中一个的一些问题:

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

答案 2 :(得分:11)

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

对于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

答案 3 :(得分:5)

我很长时间没有使用过C ++,所以我甚至都不会尝试回答你的问题(对不起);然而,Eric Lippert刚刚发布了一个关于指针/参考的excellent article,我认为我会指向你。

答案 4 :(得分:5)

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

看到语义差异也很重要:

  • 当您实际传递对象法线时使用引用 - 但它太大以至于传递对象的引用而不是复制(如果您不修改对象)更有意义。 / LI>
  • 当您想要处理内存地址而不是对象时,请使用指针。

答案 5 :(得分:4)

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

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

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

答案 6 :(得分:3)

正如其他人所提到的,在实现中,引用和指针大致相同。有一些小问题:

  • 您不能为引用分配NULL (shoosh提到这个):那是 因为没有 “未定义”或“无效”引用 值。

  • 你可以传递一个临时的 变量为 const 引用, 但传递指针是不合法的 暂时的。

例如,这没关系:

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) );
}
  • 获取变量的地址以获取指针会强制编译器将其保存到内存中。分配对局部变量的引用只会创建一个同义词;在某些情况下,这可能允许编译器将数据保留在寄存器中并避免load-hit-store。但是,这仅适用于局部变量 - 一旦通过引用将某些内容作为参数传递,就无法避免将其保存到堆栈中。

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) );
}
  • 同样,__restrict keyword不能应用于引用,只能应用于指针。

  • 你不能用引用做指针运算,所以如果你有一个指向数组的指针,那么数组中的下一个元素可以通过p + 1,只有一个引用指向它的整个生命。

答案 7 :(得分:1)

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