什么时候按值返回好吗?

时间:2016-12-13 10:14:09

标签: c++ stl eigen

我仍然不太确定何时返回值是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 ++的移动功能,通过重用基础数据来廉价地复制。

如果不完全了解实施情况,我可以假设什么?

2 个答案:

答案 0 :(得分:3)

在您声明局部变量,初始化并按值返回的情况下,您可以非常安全地假设您的编译器将elide副本。

这种情况称为命名的返回值优化。本质上,它不是在函数调用中分配返回值,而是在调用站点完成并作为引用传入。按价值返回是这里的最佳选择,因为您不需要在呼叫站点声明变量以传入,但性能将与您一样。

在C ++ 17中,copy elision will be mandatory在大多数情况下涉及prvalues(例如T t = get_t();return get_t()),但对于NRVO仍然是可选的。

答案 1 :(得分:2)

关于C ++中返回值的Thumb规则是:

  1. 永远不会返回对本地变量的引用
  2. 永远不会返回指向本地变量的指针
  3. 不使用移动语义返回命名值
  4. 至于(3) - 这是C ++的一个已知问题 - 我们都知道当一个对象按值返回时 - 它会激活复制构造函数。这理论上是真的,但几乎错误。打开优化时,编译器将在对象上使用 copy elision

    copy elision 是一种优化技术,可以在调用者范围内而不是在被调用者范围内创建值,从而防止昂贵的副本。对该对象的修改将在被调用者范围内进行。

    对于(1)和(2),还有关于协同程序和生成器的角落情况,但除非您知道您正在处理它们,否则(1)和(2)始终有效。