C ++向量,返回与参数

时间:2010-09-13 18:30:26

标签: c++ stl vector

  

可能重复:
  how to “return an object” in C++

我想知道以下三种方法之间是否存在差异:

void FillVector_1(vector<int>& v) {
    v.push_back(1); // lots of push_backs!
}

vector<int> FillVector_2() {
    vector<int> v;
    v.push_back(1); // lots of push_backs!
    return v;
}

vector<int> FillVector_3() {
    int tab[SZ] = { 1, 2, 3, /*...*/ };
    return vector<int>(tab, tab + SZ);
}

6 个答案:

答案 0 :(得分:16)

最大的区别在于第一种方式附加到现有内容,而另外两种方式填充空向量。 :)

我认为您要查找的关键字是return value optimization,这应该是相当常见的(使用G ++,您必须专门关闭它以防止它被应用)。也就是说,如果用法如下:

vector<int> vec = fill_vector();

然后可能很容易就没有副本(并且该功能更容易使用)。

如果您正在使用现有的载体

vector<int> vec;
while (something)
{
    vec = fill_vector();
    //do things
}

然后使用out参数将避免在循环中创建向量并复制数据。

答案 1 :(得分:9)

惯用的C ++方法是使用输出迭代器抽象容器类型:

template<typename OutputIterator>
void FillContainer(OutputIterator it) {
    *it++ = 1;
    ...
}

然后它可以与vector一起使用:

std::vector<int> v;
FillContainer(std::back_inserter(v));

性能(以及其他优点,例如能够填充非空容器)与您的选项#1相同。另一个好处是,如果使用了适当类型的迭代器(例如ostream_iterator),这可以用于以流模式输出,其中结果立即被处理并被丢弃而不被存储。

答案 2 :(得分:6)

人们会认为参数是最好的,但在实践中通常不是。这取决于编译器。一些编译器(我认为实际上是最新的编译器)将应用Return Value Optimization - Visual Studio 2005及更高版本应该在您提供的两种情况下都这样做(参见Named Return Value Optimization in Visual C++ 2005)。

确定最佳方法是检查生成的反汇编。

答案 3 :(得分:5)

在混音中添加第四个变体:

void FillVector_4(vector<int>& v) {
   static const int tab[SZ] = {1,2,3, ... };
   v.assign(tab,tab+SZ);
}

如果您正在考虑性能版本2和版本3 可能使编译器为返回值创建vector<int>副本。也就是说,如果编译器不能做NRVO(命名返回值优化)。此外,没有push_back的连续reserve可能导致一些重新分配,因为向量需要增长。这是否重要取决于你试图解决的问题。

您会很高兴知道C ++ 0x将使返回本地创建的向量非常有效。我还建议阅读David Abrahams article series关于有效价值类型,包括传递/返回。

答案 4 :(得分:2)

第一个肯定不会复制矢量。

复制矢量的成本在矢量中的元素数量上可以是线性的。

第一个不会在任何平台或编译器上引入线性行为的风险,也不会产生分析和重构的成本。

答案 5 :(得分:0)

乍看之下,前两个可能会更多地调整矢量大小,而第三个可能不需要在矢量运行时调整大小。这可以通过在回击之前自己调整大小来缓解。