C ++在传递值和传递引用函数之间的分配有区别吗?

时间:2010-03-22 15:00:58

标签: c++ reference variable-assignment

foo和bar之间有区别:

class A
{
  Object __o;

  void foo(Object& o)
  {
    __o = o;  
  }

  void bar(Object o)
  {
    __o = o;
  } 
} 

据我了解,foo在调用对象o时不执行复制操作,并且对赋值执行一次复制操作。 Bar在调用对象o时执行一次复制操作,而另一个用于赋值。所以我或多或少会说foo使用的内存比bar少2倍(如果o足够大)。这是对的吗?

编译器是否可以优化bar函数以仅对o执行一次复制操作?即使__o指向参数o的本地副本而不是创建新副本?

4 个答案:

答案 0 :(得分:6)

这取决于。例如,如果编译器决定内联函数,显然没有副本,因为没有函数调用。

如果你想确定,请通过const-reference:

void bar(const Object& o)

这不会复制。请注意,非const版本需要左值,因为引用是可变的。 foo(Object())不起作用,但临时值(rvalues)可以绑定到const-reference。


顺便提一下,标识符中的双下划线是为编译器保留的。

答案 1 :(得分:0)

由于赋值通常需要const Something&作为参数,因此编写规范是正常的:

  void foo(const Object& o)
  {
    __o = o;  
  }

但是这并没有回答你关于优化的问题。我不确定,一般来说,编译器可以/将会进行这样的优化。

答案 2 :(得分:0)

我认为可以说foo()执行的副本比bar()少一个。说消耗多少或多少内存并不是很有意义,因为对于简单的对象,它们存储在堆栈中并在从bar()返回后进行清理。

如前所述,请勿在标识符的开头使用下划线。

答案 3 :(得分:0)

我认为编译器可以在临时对象的情况下进行优化。这种技术称为复制省略。

请参阅我发布的what-is-copy-elision-and-how-it-optimizes-copy-and-swap-idiom问题的答案。这个ans非常有帮助What is copy elision and how does it optimize the copy-and-swap idiom?

虽然我不是这方面的专家,但据我所知,编译人员可以在某些情况下优化临时对象的复制。

例如,如果您的代码是这样调用的

bar(getObject())

其中getObject有签名

Object getObject()

此调用将导致创建Object类型的临时值。如果编译器没有进行任何优化,则必须将temporay复制到bar的参数中。

但是,如果编译器支持复制省略,则不会执行此复制,并且临时将作为参数传递给bar函数。因此避免了副本,其性能与接受引用的foo相同。但正如我所说,它仅在临时对象的情况下发生