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

时间:2014-02-06 10:17:56

标签: c++ const pass-by-reference pass-by-value

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

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

void myFunction (NonSimpleObject foo) {
  foo = ~foo;
}

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

void myFunction (NonSimpleObject &foo) {
  NonSimpleObject foo_internal = ~foo;      
}

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

void myFunction (const NonSimpleObject foo) {
  NonSimpleObject foo_internal = ~foo;
}

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

void myFunction (const NonSimpleObject &foo) {
  NonSimpleObject foo_internal = ~foo;      
}

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

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

4 个答案:

答案 0 :(得分:9)

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

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

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

答案 1 :(得分:5)

按价值传递:

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

所以,这样:

void myFunction (NonSimpleObject foo) {
   //modify foo here
}

答案 2 :(得分:1)

第一种情况(void myFunction (NonSimpleObject foo))将创建两个对象。第一个对象是foo,第二个对象是foo_internal

第二种情况(void myFunction (const NonSimpleObject &foo))将只创建一个对象 - 即foo_internal

因此,第二种情况更好。

  

在参数传递过程中复制函数而不是复制是否有任何好处,反之亦然?

如果您要使用创建的对象,请复制它。您没有显示足够的代码来判断是否需要副本。就目前而言 - 我会说使用const引用。

答案 3 :(得分:0)

“我想修改该函数中的值,但我不希望该更改在该函数之外可见。”

然后,您的意思是更改对象的本地副本。 (我认为你不是指friend - 函数,它允许你更改对象的私有数据。)

所以你需要传递by-value,而最干净的解决方案就是你的1.(而不是引用,然后在本地副本(你的2.解决方案)里面)。

这表示用户不会更改传递的对象(仅限本地副本,但这就是您想要的)。将它按值传递给const(您的3.解决方案)略有不同:您不仅告知用户,传递的对象不会被更改,而且本地副本不可更改

通过const引用传递信号,传递的对象既不会被更改也不会存在可更改的本地副本。

所以你应该考虑一下真正想要什么。