【问题标题】:Avoiding temporary variables when returning vectors from two or more functions从两个或多个函数返回向量时避免使用临时变量
【发布时间】:2020-12-26 20:11:32
【问题描述】:

我想知道在通过函数返回 std::vector 并直接在向量“整数”中“创建”它们的值时,是否有任何方法可以避免额外的副本。在 c++11 之前,最常用的方法是通过引用 (&) 传递 main std::vector 并在填充函数中使用它,但我想避免这种方法并尝试更现代的 c++ 方式。

#include <vector>

std::vector<int> function1()
{
    std::vector<int> v;
    v.emplace_back(1);
    v.emplace_back(2);
    v.emplace_back(3);
    
    return v;
}

std::vector<int> function2()
{
    std::vector<int> v;
    v.emplace_back(10);
    v.emplace_back(11);
    
    return v;
}

int main()
{
    std::vector<int> integers;
    
    const auto v1 = function1();
    std::copy(v1.begin(), v1.end(), std::back_inserter(integers));
    
    const auto v2 = function2();
    std::copy(v2.begin(), v2.end(), std::back_inserter(integers));
    
    return 0;
}

我想要的是直接在 main 中定义的向量中创建元素,如果可能的话,使用 c++11 或更高版本的功能。

提前致谢。

【问题讨论】:

  • 编译器很可能会做NRVO,把vector的内容直接放在需要的地方。 (虽然这不是必需的)。您应该查看程序集以了解发生了什么。
  • RVO 很可能发生在您的情况下,并且复制将被忽略。就像你似乎想要的那样。请更具体地说明所显示代码的问题。
  • 您的意思是避免创建临时的v1v2 子向量,还是只关心v1v2 是在没有复制的情况下构造的?
  • 澄清一下,您要避免使用 v1v2 变量,并能够使用例如function1() 直接在调用std::copy?使用普通的 C++11 是不可能的。可以使用C++20 ranges 直接插入integers。并且也可能使用 the ranges-v3 library 在较旧的变体中进行。
  • ranges::join/ranges::concat 将允许从现有的v1v2 中拥有一个惰性范围。我们可能期望使用 co_routine 生成器(C++20 ++)从多个生成器创建向量/生成器(以避免v1/v2)类似的事情...

标签: c++ c++11 rvo


【解决方案1】:

如果你这样写你的函数:

std::vector<int> function1()
{
    return std::vector<int> {1, 2, 3};
}

std::vector<int> function2()
{
    return std::vector<int> {10, 11};
}

那么从c++17开始,RVO是强制的,向量会直接在调用点构造。


从 c++20 开始,您可以完全避免在 main 中创建向量,方法是:

std::ranges::copy(function1(), std::back_inserter(integers));
std::ranges::copy(function2(), std::back_inserter(integers));

【讨论】:

  • 不是投票者,但似乎实际问题(来自 cmets)是(我的想法)“我想知道是否可以避免临时 v1 和 v2 向量并直接在整数上创建矢量".
  • @cigien 我也不是反对者,感谢您帮助我!我赞成你教我范围,但由于限制,我不能使用 c++20 功能,所以我想我无法做到这一点,除非使用第三方库作为范围-v3,这不是我的项目负担得起的过度工作。
  • @Pablo 没问题,乐于助人 :) 就算现在不能用,以后也知道用什么了 :)
猜你喜欢
  • 2018-03-26
  • 1970-01-01
  • 2012-04-30
  • 1970-01-01
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
相关资源
最近更新 更多