C++向量,返回与参数

Mar*_*son 10 c++ stl vector

可能重复:
如何在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);
}
Run Code Online (Sandbox Code Playgroud)

Unc*_*ens 16

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

我认为您正在寻找的关键字是返回值优化,这应该是相当普遍的(使用G ++,您必须专门关闭它以防止它被应用).也就是说,如果用法如下:

vector<int> vec = fill_vector();
Run Code Online (Sandbox Code Playgroud)

然后可能很容易就没有副本(而且功能更容易使用).

如果您正在使用现有向量

vector<int> vec;
while (something)
{
    vec = fill_vector();
    //do things
}
Run Code Online (Sandbox Code Playgroud)

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


Pav*_*aev 9

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

template<typename OutputIterator>
void FillContainer(OutputIterator it) {
    *it++ = 1;
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

std::vector<int> v;
FillContainer(std::back_inserter(v));
Run Code Online (Sandbox Code Playgroud)

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


Sum*_*uma 6

人们会认为参数是最好的,但实际上通常不是.这取决于编译器.一些编译器(我认为实际上是最新的编译器)将应用返回值优化 - Visual Studio 2005及更高版本应该在您提供的两种情况下都执行它(请参阅Visual C++ 2005中的命名返回值优化).

确切知道的最好方法是检查生成的反汇编.


sel*_*tze 5

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

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

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

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