4

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

例如这是:

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();

谢谢,保罗


编辑: 这是 C++03。不幸的是,C++0x 解决方案是不可接受的。

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

4

5 回答 5

6

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

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

于 2011-02-17T21:08:33.480 回答
3

我不是 100% 确定,但没有(感谢评论员):

#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) 产生了一些乐趣。所以一个不优化复制的非常糟糕的编译器实际上可以破坏这段代码......

于 2011-02-17T21:12:35.603 回答
2

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

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

于 2011-02-17T21:08:43.467 回答
0

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

于 2011-02-17T21:13:09.413 回答
0

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

于 2011-02-17T21:15:43.533 回答