新手,我正在阅读一些代码,有时我看到作者在函数中使用了引用作为
funca (scalar& a)
// Etc
有时他只是使用
funcb (scalar a)
// Etc
有什么不同?使用参考是我应该养成的好习惯吗?
谢谢!
新手,我正在阅读一些代码,有时我看到作者在函数中使用了引用作为
funca (scalar& a)
// Etc
有时他只是使用
funcb (scalar a)
// Etc
有什么不同?使用参考是我应该养成的好习惯吗?
谢谢!
如果您调用,类型foo(scalar a)
的参数将从调用者那里复制,而 foo 将拥有原始对象的自己的副本。a
scalar
如果您调用foo(scalar &b)
,参数b
将只是对原始对象的引用,因此您将能够修改它。
使用 &name 语法通过引用传递对象更快,因为它避免了创建给定对象的副本,但它可能存在潜在危险,有时这种行为是不需要的,因为您只想要一个实际的副本。
话虽如此,实际上有一个选项不允许修改被调用函数的原始对象但避免创建副本。它foo(const scalar &x)
明确指出调用者不希望函数foo
修改作为参数传递的对象。
选读,仔细:
还有一种将参数作为原始指针传递的方法,这在现代 C++ 中非常罕见。谨慎使用:foo(scalar *a)
. 在这种情况下,调用者必须提供对象的地址而不是对象本身,因此调用者会调用foo(&a)
. 在这种情况下,为了让被调用函数foo
能够修改对象本身,它需要取消引用指针a
,就像在foo
:中一样*a =
。在这种情况下,变量名前面的星号表示我们不想修改我们收到的地址(作为调用函数提供的直接结果&a
,即对象a的地址)。
通过引用传递参数允许被调用函数以在函数返回后对调用者可见的方式修改其参数,而通过值传递意味着任何更改都将限制在被调用函数的范围内。因此,通过(非常量)引用传递通常表示被调用者打算修改参数,或者不太常见地将其用作附加的“返回值”。
此外,通过引用传递意味着不需要复制参数;按值传递需要这样的副本(这可能不利于应用程序的内存占用或运行时性能)。出于这个原因,您经常会看到类类型的参数作为const
引用传递:被调用者不打算修改参数,但它也希望避免复制。标量参数的大小非常小,因此它们不会从这种方法中受益。
另请参阅C++ 中的通过引用/值传递。
按值调用 ( funcb (scalar a)
) 将为函数提供参数的副本,因此对参数所做的更改对调用者不可见。
通过引用调用 ( funcb(scalar& b)
) 意味着函数直接对参数进行操作,因此所做的任何更改对调用者都是直接可见的。
通过引用调用是否是一种好的做法取决于具体情况。如果您需要该函数来修改参数(以及对调用者可见的修改),您显然希望使用引用调用。如果您不想使用非常量引用参数修改参数会产生误导(因为签名表明参数可以更改),因此此处按值调用更合适。当然,对于更复杂的类型,按值调用可能会有不小的开销。在这些情况下,按常量引用调用更可取 ( funcc(const scalar& c)
)