在c++中,通过指针传递比通过引用传递有什么好处?

最近,我看到了许多选择通过指针传递函数参数而不是通过引用传递函数参数的例子。这样做有好处吗?

例子:

func(SPRITE *x);

伴随着一声呼唤

func(&mySprite);

vs.

func(SPRITE &x);

伴随着一声呼唤

func(mySprite);

当前回答

传递指针

调用者必须取地址->不透明 0值可以提供为没有任何意义。这可用于提供可选参数。

通过引用传递

Caller just passes the object -> transparent. Has to be used for operator overloading, since overloading for pointer types is not possible (pointers are builtin types). So you can't do string s = &str1 + &str2; using pointers. No 0 values possible -> Called function doesn't have to check for them Reference to const also accepts temporaries: void f(const T& t); ... f(T(a, b, c));, pointers cannot be used like that since you cannot take the address of a temporary. Last but not least, references are easier to use -> less chance for bugs.

其他回答

我喜欢“cplusplus.com”上一篇文章的推理:

Pass by value when the function does not want to modify the parameter and the value is easy to copy (ints, doubles, char, bool, etc... simple types. std::string, std::vector, and all other STL containers are NOT simple types.) Pass by const pointer when the value is expensive to copy AND the function does not want to modify the value pointed to AND NULL is a valid, expected value that the function handles. Pass by non-const pointer when the value is expensive to copy AND the function wants to modify the value pointed to AND NULL is a valid, expected value that the function handles. Pass by const reference when the value is expensive to copy AND the function does not want to modify the value referred to AND NULL would not be a valid value if a pointer was used instead. Pass by non-cont reference when the value is expensive to copy AND the function wants to modify the value referred to AND NULL would not be a valid value if a pointer was used instead. When writing template functions, there isn't a clear-cut answer because there are a few tradeoffs to consider that are beyond the scope of this discussion, but suffice it to say that most template functions take their parameters by value or (const) reference, however because iterator syntax is similar to that of pointers (asterisk to "dereference"), any template function that expects iterators as arguments will also by default accept pointers as well (and not check for NULL since the NULL iterator concept has a different syntax). http://www.cplusplus.com/articles/z6vU7k9E/

我从中得到的是,选择使用指针或引用参数的主要区别是NULL是否为可接受的值。就是这样。

不管这个值是输入的、输出的、可修改的等等,都应该在关于函数的文档/注释中。

Allen Holub在《足够的绳子砸自己的脚》一书中列出了以下2条规则:

120. Reference arguments should always be `const`
121. Never use references as outputs, use pointers

他列出了在c++中添加引用的几个原因:

它们是定义复制构造函数所必需的 它们是操作符重载所必需的 Const引用允许使用值传递语义,同时避免复制

他的主要观点是引用不应该被用作“输出”参数,因为在调用点没有指示参数是引用还是值参数。他的规则是只使用const引用作为参数。

就我个人而言,我认为这是一个很好的经验法则,因为它可以更清楚地说明参数何时是输出参数。然而,虽然我个人总体上同意这一点,但我确实允许自己受到团队中其他人的意见的影响,如果他们主张将输出参数作为参考(一些开发人员非常喜欢它们)。

以上职位说明:


引用不能保证得到一个非空指针。(尽管我们经常这样对待他们。)

而可怕的坏代码,就像把你带出木棚后面的坏代码一样,下面的代码将编译和运行:(至少在我的编译器下)。

bool test( int & a)
{
  return (&a) == (int *) NULL;
}

int
main()
{
  int * i = (int *)NULL;
  cout << ( test(*i) ) << endl;
};

我对引用的真正问题在于其他程序员,他们在构造函数中分配,在析构函数中释放,并且不能提供复制构造函数或operator=()。

突然之间,foo(BAR BAR)和foo(BAR & BAR)之间有了一个不同的世界。(自动逐位复制操作被调用。析构函数中的释放会被调用两次。)

值得庆幸的是,现代编译器可以对同一个指针进行双重释放。15年前,他们没有。(在gcc/g++下,使用setenv MALLOC_CHECK_ 0来重新使用旧的方法。)结果,在DEC UNIX下,同一内存被分配给两个不同的对象。那里有很多调试的乐趣……


更实际:

引用隐藏了您正在更改存储在其他地方的数据。 引用和复制对象很容易混淆。 指针使它变得明显!

不是真的。在内部,按引用传递实际上是通过传递被引用对象的地址来执行的。因此,传递一个指针并不能提高任何效率。

不过,通过引用传递确实有一个好处。保证你有一个传入的任何对象/类型的实例。如果传入一个指针,则会有接收到空指针的风险。通过使用引用传递,您将隐式null检查推到函数的调用者的上一层。

指针可以接收NULL形参,而引用形参不能。如果你有机会想要传递“无对象”,那么使用指针而不是引用。

另外,通过指针传递可以让你显式地在调用点看到对象是通过值传递还是通过引用传递:

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);