何时按值返回OK

When is return by value ok?

本文关键字:OK 返回 何时按      更新时间:2023-10-16

我仍然不确定当by-by-value何时在c 中是一个好主意。在下种情况下,可以吗?

vector<int> to_vec(const Eigen::MatrixXi& in){
    vector<int> out;
    // copy contents of in into out
    return out;
}
Eigen::MatrixXi to_eigen(const vector<int>& in){
    Eigen::MatrixXi out;
    // copy contents of in into out
    return out
}

根据这些对象vectorMatrixXi的实际工作方式,可能会导致昂贵的副本。另一方面,我认为他们利用C 的s 移动功能来廉价地通过重复使用基础数据来复制。

在不完全知道实现的情况下,我可以假设什么?

在这种情况下,您要声明局部变量,对其进行初始化并按值返回,因此假设您的编译器会弹出副本,则可以非常安全。

此情况称为命名返回值优化。从本质上讲,它不会在函数调用中分配返回值,而是在呼叫站点上完成并作为参考通过。按值返回是这里的最佳选择,因为您无需在呼叫站点上声明一个变量即可传递,但是性能将好像您有。

在C 17中,在大多数情况下,副本将是强制性的(例如T t = get_t();return get_t()),但对于NRVO仍然是可选的。

有关C 中返回值的拇指规则为:

  1. 永远不要返回对本地变量的引用
  2. 永远不要将指针返回到本地变量
  3. 不要使用移动语义返回命名值

至于(3) - 这是C 的已知问题 - 我们都知道,当对象按值返回时 - 它会激活复制构造函数。这是理论上 true,但实际上是错误。当打开优化时,编译器将在对象上使用在对象上复制Elision

复制ELISION 是一种优化技术,可以在呼叫者范围内而不是在Callee范围内创建该值,从而防止昂贵的副本。该对象的修改将发生在Callee范围中。

至于(1)和(2),也有一个有关Coroutines和Generator的角案,但是除非您知道您正在与它们打交道,否则(1)和(2)始终有效。