C++ 指针和引用参数之间的区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/620604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:17:51  来源:igfitidea点击:

difference between a pointer and reference parameter?

c++pointersreferenceobject-slicing

提问by criddell

Are these the same:

这些是一样的吗:

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

and

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

Ignore the null pointer potential. Are these two functions functionally identical no matter if someInt()is virtual or if they are passed a baror a subclass of bar?

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

Does this slice anything:

这是否切片任何东西:

bar& ref = *ptr_to_bar;

回答by shoosh

C++ references are intentionally not specified in the standard to be implemented using pointers. A reference is more like a "synonym" to a variable than a pointer to it. This semantics opens some possible optimizations for the compiler when it's possible to realize that a pointer would be an overkill in some situations.

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

A few more differences:

还有一些区别:

  • You can't assign NULL to a reference. This is a crucial difference and the main reason you'd prefer one over the other.
  • When you take the address of a pointer, you get the address of the pointer variable. When you take the address of a reference, you get the address of the variable being referred to.
  • You can't reassign a reference. Once it is initialized it points to the same object for its entire life.
  • 您不能将 NULL 分配给引用。这是一个至关重要的区别,也是您更喜欢其中一个的主要原因。
  • 当您获取指针的地址时,您将获得指针变量的地址。当您获取引用的地址时,您将获得被引用的变量的地址。
  • 您不能重新分配参考。一旦它被初始化,它就会在它的整个生命周期中指向同一个对象。

回答by Johannes Schaub - litb

Ignoring every syntactic sugar and possibilities that can be done with the one and not with the other and difference between pointers and references explained in other answers (to other questions) ... Yeah those two are functionally exactly the same! Both call the function and both handle virtual functions equally well.

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

And no, your line does not slice. It's just binding the reference directly to the object pointed to by a pointer.

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

Some questions on why you would want to use one over the other:

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

Instead of trying to come up with differences myself, i delegate you to those in case you want to know.

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

回答by Vinay

Reference is a constant pointer i.e., you can't change the reference to refer to other object. If you change, value of the referring object changes.

引用是一个常量指针,即您不能更改引用以引用其他对象。如果您更改,则引用对象的值会更改。

For 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

回答by Patrick Glandien

Yes they are functionally identical. Since a reference will require you to set it to an object before using it, you wont have to deal with null-pointers or pointers to invalid memory.

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

It is also important to see the semantical difference:

查看语义差异也很重要:

  • Use a reference when you would actually pass the object normal - but it is so large that it makes more sense to pass a reference to the object rather than making a copy (if you are not modifying the object that is).
  • Use a pointer when you want to deal with the memory address rather than with the object.
  • 当您实际将对象正常传递时使用引用 - 但它是如此之大,以至于将引用传递给对象而不是制作副本(如果您没有修改对象)更有意义。
  • 当您想处理内存地址而不是对象时,请使用指针。

回答by Chris Shaffer

I haven't used C++ in a long time, so I'm not even going to attempt to really answer your question (sorry); However, Eric Lippert just posted an excellent articleabout pointers/references that I figured I'd point you to.

我已经很久没有使用 C++,所以我什至不打算真正回答你的问题(抱歉);然而,Eric Lippert 刚刚发布了一篇关于指针/引用的优秀文章,我想我会指出你的。

回答by Dan

Not sure if anyone answered your 2nd question hidden at the bottom about slicing... no that won't cause slicing.

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

Slicing is when a derived object is assigned (copied) to a base class object -- the derived class's specialization is "sliced" off. Note that I said the objectis copied, we're not talking about pointers being copied/assigned, but the objects themselves.

切片是指派生对象被分配(复制)给基类对象——派生类的特化被“切片”掉。请注意,我说对象是被复制的,我们不是在谈论被复制/分配的指针,而是对象本身。

In your example, that's not happening. You're just de-referencing a pointer to a Bar object (thereby resulting in a Bar object) being used as the rvalue in a reference initialization. Not sure I got my terminology right...

在你的例子中,这不会发生。您只是取消引用一个指向 Bar 对象的指针(从而产生一个 Bar 对象),用作引用初始化中的右值。不确定我的术语是否正确...

回答by Crashworks

As everyone else has mentioned, in implementation references and pointers are largely the same. There are some minor caveats:

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

  • You can't assign NULL to a reference (shoosh mentioned this): that's significant since there is no "undefined" or "invalid" reference value.

  • You can pass a temporary variable as a constreference, but it's not legal to pass a pointer to a temporary.

  • 您不能将 NULL 分配给引用(shoosh 提到了这一点):这很重要,因为没有“未定义”或“无效”的引用值。

  • 您可以将临时变量作为常量引用传递,但将指针传递给临时变量是不合法的。

For example, this is okay:

例如,这是可以的:

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

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

but most compilers will complain about

但大多数编译器会抱怨

void foo2( Thingy * a);

void bar2()
{
  foo( &Thingy(1,2) );
}
  • Taking the address of a variable to get a pointer forces the compiler to save it to memory. Assigning a reference to a local variable just creates a synonym; in some cases this may allow the compiler to keep the data on the register and avoid a load-hit-store. However, this only applies to local variables -- once something is passed as a parameter by reference, there's no avoiding saving it to stack.
  • 获取变量的地址以获取指针会强制编译器将其保存到内存中。分配对局部变量的引用只会创建一个同义词;在某些情况下,这可能允许编译器将数据保存在寄存器上并避免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) );
}
  • Similarly, the __restrict keywordcannot be applied to references, only pointers.

  • You can't do pointer arithmetic with references, so whereas if you have a pointer into an array then the next element in the array can be had through p+1, a reference only ever points at one thing in its entire life.

  • 同样,__restrict 关键字不能应用于引用,只能应用于指针。

  • 你不能用引用进行指针算术,所以如果你有一个指向数组的指针,那么数组中的下一个元素可以通过 p+1 获得,一个引用在其整个生命周期中只指向一件事。

回答by Crashworks

The functions are obviously not "the same", but with regard to virtual behaviour they will behave similarly. Regarding slicing, this only happens when you deal withvalues, not references or pointers.

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