返回标准容器会产生容器内容的副本吗?

时间:2011-02-17 21:03:59

标签: c++ optimization stl containers standard-library

如果我有一个返回STL容器的函数我是否会生成标准容器的全部内容的副本?

e.g。是这样的:

void Foo( std::vector< std::string >* string_list );

比这更好:

std::vector< std::string > Foo();

容器中的内容是否重要?例如,会返回一个像这样的容器:

struct buzz {
    int a;
    char b;
    float c;
}

std::map< int, buzz > Foo();

比这更昂贵的操作:

std::map< int, int > Foo();

谢谢, PaulH


修改 这是使用C ++ 03。遗憾的是,C ++ 0x解决方案是不可接受的。

EDIT2: 我正在使用Microsoft Visual Studio 2008编译器。

5 个答案:

答案 0 :(得分:6)

C ++ 03可能会做(命名)返回值优化(谷歌RVO和NRVO)。

如果该优化不适用,C ++ 0x将执行move semantics

答案 1 :(得分:3)

我不是百分百肯定,但是没有(感谢评论员):

#include <vector>
#include <iostream>

#define LOCAL_FUN

struct A {
    A() { std::cout << "default ctor" << std::endl; }
    A(const A &a) { std::cout << "copy ctor" << std::endl; }
};

#ifdef LOCAL_FUN
std::vector<A> *pVec = NULL;
#endif

std::vector<A> func()
{
    std::vector<A> vec;
#ifdef LOCAL_FUN
    pVec = &vec;
#endif
    vec.push_back(A());
    std::cout << "returning" << std::endl;
    return vec;
}

int main(int argc, char *argv[])
{
    std::vector<A> ret = func();
#ifdef LOCAL_FUN
    if (pVec) {
        std::cout << pVec->size();
    }
#endif
}

输出(使用LOCAL_FUN):

default ctor
copy ctor
returning
1

编辑:使用代码更多的玩法让我对局部变量(LOCAL_FUN)有了一些乐趣。因此,一个不优化复制的非常糟糕的编译器实际上可以破坏这段代码......

答案 2 :(得分:2)

是的,它将涉及容器的副本,但不要使用void Foo( std::vector< std::string >* string_list );。请改用void foo( vector<string>& string_list);

或者只是切换到C ++ 0x并使用已经移动了库中实现的优化的编译器。

答案 3 :(得分:0)

第一个编译器需要删除复制构造,如果不能,则移动,如果不能再复制。因此,如果您的编译器非常糟糕,则可能会产生额外副本的开销。有关详细信息,请参阅this discussion

答案 4 :(得分:0)

这取决于容器的复制构造函数。 C ++具有传递值语义。因此,当您返回函数Foo()的向量时,它将使用值语义返回,即将调用复制构造函数来复制向量的值。在这种情况下,std :: vector的复制构造函数创建一个新容器并复制值。在将指针传递给容器的情况下,如果尚未分配内存,则必须分配内存,以便指针指向实际容器而不是空值。从编程实践的角度来看,这不是一件好事,因为你可以将语义留给解释。更好的想法是传递对容器的引用,让函数用所需的元素填充容器。