这些是否相同:
int foo(bar* p) {
return p->someInt();
}
和
int foo(bar& r) {
return r.someInt();
}
忽略空指针潜力。这两个函数在功能上是否相同,无论someInt()
是虚拟的还是传递bar
或bar
的子类?
这会切片吗:
bar& ref = *ptr_to_bar;
答案 0 :(得分:64)
有意在未使用指针实现的标准中指定C ++引用。引用更像是变量的“同义词”而不是指向它的指针。当在某些情况下可能意识到指针过大时,这种语义会为编译器打开一些可能的优化。
还有一些差异:
答案 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)
是的,它们在功能上完全相同。由于引用将要求您在使用它之前将其设置为对象,因此您不必处理空指针或指向无效内存的指针。
看到语义差异也很重要:
答案 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) );
}
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)
这些功能显然不是“相同”,但就虚拟行为而言,它们的行为类似。关于切片,这只发生在处理值时,而不是引用或指针。