【问题标题】:What is the best way to return a vector from a function in c++ [duplicate]从c ++中的函数返回向量的最佳方法是什么[重复]
【发布时间】:2013-10-31 10:04:43
【问题描述】:

我有一个函数可以返回这样的数组:

vector<string> GetString()
{
   vector<string> s;
   s.push_back("one");
   s.push_back("two");
   s.push_back("three");
   return s;
}

我这样称呼它:

   vector<string> mystrings=GetStrings();

我也可以如下实现:

void GetString(vector<string> & s)
{
   s.push_back("one");
   s.push_back("two");
   s.push_back("three");
}

并以这种方式调用它:

 vector<string> mystrings;
 GetStrings(mystrings);

哪个更好?

第一个版本是否将向量复制到另一个?如果是,那么如果向量很大,它就会很慢。

【问题讨论】:

标签: c++ stl


【解决方案1】:

哪个更好?

他们做不同的事情。如果您想要一个仅包含这些字符串的向量,请使用第一个;如果您希望能够将这些字符串附加到现有向量,请使用第二个。

如果您想要第一个版本的语义,那么从更容易正确使用和更难错误使用的意义上说,这是“更好的”。

第一个版本是否将向量复制到另一个?

在现代 C++ 中,绝对不是:返回局部变量和从临时变量初始化都是通过移动而不是复制来完成的。即使您坚持使用 C++11 之前的编译器,也应该忽略这两个副本。如果你的编译器不支持移动语义或复制省略,那么你真的应该把它扔掉。

【讨论】:

  • 但是我接受它作为答案,但我仍然无法理解:对象是在堆栈中创建的,从函数返回后,创建对象的堆栈会回滚,所以我们需要复印件。我们如何回滚堆栈并消除复制和使用移动?这里的移动意味着什么以及它是如何完成的?
  • @mans:复制省略意味着对象是在调用者的栈帧中创建的,所以返回时不需要复制。移动意味着向量的内容通过更新它们的内部指针而不是通过复制元素来转移到另一个向量。任何体面的编译器都应该支持省略,但这不是强制性的。所有 C++11 编译器都必须支持移动语义。
【解决方案2】:

这主要是个人偏好问题,以及您可能需要使用的任何编码约定。

在 C++11 之前,有时会认为第二种方法更可取。性能保证是好的,因为没有不必要的复制。另一方面,第一种方法有可能(理论上)调用一个相当昂贵的复制构造函数。

但在实践中,称为复制省略的优化通常会避免复制构造函数,这意味着无论哪种方式性能都一样好。但不能保证,因为它可能取决于编译器设置/功能等因素。

C++11 引入了移动语义。它提供了一种消除复制的替代方法,并且内置于语言规范中(而不是可选的编译器优化)。从可读性的角度来看,这可以使第一个选项更可取,因为您的代码在做什么可能更明显。

【讨论】:

    猜你喜欢
    • 2013-05-18
    • 2010-09-07
    • 2012-10-23
    • 2013-03-30
    • 2010-09-30
    • 2017-02-04
    • 2010-10-16
    • 1970-01-01
    相关资源
    最近更新 更多