按值,const值,引用或const引用传递非POD类型

Cha*_*_99 3 c++ const pass-by-reference pass-by-value

我需要将非POD类型传递给C++函数.我想修改该函数内部的值,但我不希望该更改在该函数之外可见.

我的第一个选择是传递值,这会创建一个副本.

void myFunction (NonSimpleObject foo) {
  foo = ~foo;
}
Run Code Online (Sandbox Code Playgroud)

我也可以通过引用传递,这在函数调用期间更快,但是我需要在里面创建一个不影响外部值的副本;

void myFunction (NonSimpleObject &foo) {
  NonSimpleObject foo_internal = ~foo;      
}
Run Code Online (Sandbox Code Playgroud)

要向调用者发出不会修改外部值的信号,我想包含一个const限定符.当按值调用时,这当然是隐含的,但我想更加冗长.但传递一个const值将迫使我在里面创建第二个副本来修改该值,这也与const限定符最初使用的内容有些相反.

void myFunction (const NonSimpleObject foo) {
  NonSimpleObject foo_internal = ~foo;
}
Run Code Online (Sandbox Code Playgroud)

传递一个const引用都会向调用者发出信号,表明外部值没有改变,只需要在函数内部有一个副本.

void myFunction (const NonSimpleObject &foo) {
  NonSimpleObject foo_internal = ~foo;      
}
Run Code Online (Sandbox Code Playgroud)

哪一个最适合我的目的(良好的性能,对调用者来说冗长)以及优点/缺点是什么?

这也归结为以下问题:在参数传递期间复制内部函数而不是复制是否有任何优势,反之亦然?

Mik*_*our 9

如果需要本地对象,则最好通过值传递.如果参数是临时的或显式移动的,则这使得移动语义成为可能,从而可以避免不必要的复制.

通过引用传递强制复制是否需要.如果引用不是const,则参数不能是临时的.const按值接受对象然后复制它只是很奇怪.

(请注意,在您的特定示例中,您不需要本地副本,只需要将操作符应用于参数;因此const引用可能更合适.)


JBL*_*JBL 5

只需按值传递:

  • 它会创建一个副本(并且不需要为它编写任何代码,即显式副本)
  • 关于你对你正在做什么的语义的关注:通过值传递的参数使得调用代码清楚地表明你没有修改函数内部的对象,你创建了它的副本,以及原始对象将保持不变.const当它是你传递给函数的实际对象(即带参考)并且你希望它不被修改(例如只是为了"窥视"它)时,可以更好地使用它.
  • 通过引用传递将需要您手动创建副本,这通过按值传递来完成.

所以,这样:

void myFunction (NonSimpleObject foo) {
   //modify foo here
}
Run Code Online (Sandbox Code Playgroud)