代码之家  ›  专栏  ›  技术社区  ›  Rémy DAVID

C++在传递值内的赋值与传递函数之间有区别吗?

  •  2
  • Rémy DAVID  · 技术社区  · 16 年前

    foo和bar有区别吗?

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

    据我所知,foo在调用对象o时不对其执行复制操作,并为赋值执行一个复制操作。当对象o被调用时,bar对其执行一个复制操作,另一个用于赋值。所以我可以或多或少地说foo使用的内存是bar的2倍(如果o足够大)。是这样吗?

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

    4 回复  |  直到 16 年前
        1
  •  6
  •   GManNickG    16 年前

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

    如果要确定,请传递常量引用:

    void bar(const Object& o)
    

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


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

        2
  •  0
  •   Daniel Daranas    16 年前

    因为分配通常需要 const Something& 作为一个参数,写入:

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

    但这并不能回答你关于优化的问题。一般来说,我不确定编译器是否能够/将进行这种优化。

        3
  •  0
  •   quamrana Ryuzaki L    16 年前

    我认为这样说是公平的 foo() 执行的副本比 bar() . 说内存消耗多少并不是很有意义,因为对于简单的对象,它们存储在堆栈中,并在从返回后清除 巴尔) .

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

        4
  •  0
  •   Community Mohan Dere    9 年前

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

    请参考我发布的问题的答案 what-is-copy-elision-and-how-it-optimizes-copy-and-swap-idiom . 这个答案真的很有用 What is copy elision and how does it optimize the copy-and-swap idiom?

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

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

    bar(getObject())
    

    哪里 getObject 有签名

    Object getObject()
    

    此调用将导致创建类型为 Object . 如果编译器没有进行任何优化,则必须将templay复制到 bar .

    但是,如果编译器支持复制省略,则不会执行此复制,并且临时的将作为参数传递给 酒吧 功能。因此避免了复制,其性能与 foo 它接受一个引用。但正如我所说,只有在临时物体