【问题标题】:What happens in C++ if a function return value is passed to a function reference argument?如果将函数返回值传递给函数引用参数,在 C++ 中会发生什么?
【发布时间】:2021-06-09 06:16:34
【问题描述】:

让我们考虑两个函数:

//Test functions
Object MakeObj(){/* processsing */};
Object ChangeObj(const Object& obj){/* processsing */};
//Then execute
Object test_obj = ChangeObj(MakeObj());
  1. 执行是否安全?

  2. MakeObj() 的“Object”返回值存储在哪里?我可以使用对该存储的引用吗?

  3. 或者需要一个临时变量:

    Object MakeObj(){/* processsing */};
    Object ChangeObj(const Object& obj){/* processsing */};
    Object tmp_obj = MakeObj();
    Object test_obj = ChangeObj(tmp_obj);
    
  4. 如果第 3 点的代码发生更改,是否有任何性能提升或完全相同:

    Object MakeObj(){/* processsing */};
    Object ChangeObj(Object obj){/* processsing */}; //No reference here, so 'Object' value is created.
    Object test_obj = ChangeObj(MakeObj());
    
  5. 有没有办法使用“移动”来避免应对大对象?例如:

    Object ChangeObj(Object&& obj){/* processsing */};
    

    如果是,它会是什么样子?

  6. 上面这两个功能的最快实现(尽可能少的应对)是什么?假设:“对象 MakeObj();”声明不能更改。

【问题讨论】:

  • Object test_obj = ChangeObj(MakeObj()); 不会编译,所以你不用担心。
  • && 不仅仅是一个“移动”引用,还称为“通用”甚至“右值”引用。它被称为右值引用,因为您可以将它用于右值,就像 MakeObj() 返回的那样。
  • 当某个对象从函数返回时,它通常会这样工作,即调用者在其堆栈上为该对象分配存储空间,然后将其地址作为隐藏参数传递给被调用函数。然后,此函数可能(或必须)直接在此存储中创建返回的对象。现场演示:godbolt.org/z/KEhqvvKoW(存储地址传入rdif)。但是,一般来说,整个问题要复杂得多(例如,通常在寄存器中传递小的琐碎对象)。
  • ChangeObject 在做什么?为什么它通过非常量引用获取参数并且返回Object
  • 使参数成为 const 引用的编辑变化很大。我认为变化使这是一个全新的问题。

标签: c++ performance reference return copy


【解决方案1】:
  1. 执行是安全的,因为const reference extends object lifetime(或here

  2. 对象本身存储在堆栈的某处,但只要存在 const 引用就不会被擦除(compareasm line 20(non-reference) and 25-27(const reference))

  3. 没有。没必要。

  4. 在一般情况下,第 4 点的代码更快,即使有 move(在 vector 的情况下,优化 2-3 次赋值操作 size_t

  5. move 只能应用在第 3 点的代码中,然后它看起来像

Object MakeObj(){/* processsing */};
Object ChangeObj(Object&& obj){/* processsing */};
Object tmp_obj = MakeObj();
Object test_obj = ChangeObj(std::move(tmp_obj));
//here tmp_obj is no longer valid
  1. 第 4 点中的代码应该是最快的,但是要测量!!!记住优化的第一条规则:不要过早优化

【讨论】:

  • 我意识到介绍中的代码是最快的,比第 4 点要快,因为它少了一个“对象”变量创建。感谢您的回答。
  • 但是 RVO 应该优化过度的对象创建 @JerzyJamroz
猜你喜欢
  • 2022-11-26
  • 2020-11-27
  • 2021-02-12
  • 2015-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多