退回标准容器是否会产生容器内容物的副本?

发布于 2024-10-18 07:45:25 字数 609 浏览 3 评论 0原文

如果我有一个返回 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();

谢谢, PaulH


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

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

If I have a function that returns an STL container am I incurring a copy of the entire contents of the standard container?

e.g. Is this:

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

better than this:

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

Does it matter what's in the container? For instance would returning a container like this:

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

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

be a more costly operation than this:

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

Thanks,
PaulH


Edit:
This is with C++03. A C++0x solution is, unfortunately, not acceptable.

Edit2:
I am using the Microsoft Visual Studio 2008 compiler.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

七色彩虹 2024-10-25 07:45:26

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

如果该优化不适用,C++0x 将移动语义

C++03 will probably do (named) return value optimization (google RVO and NRVO).

If that optimization is not applicable, C++0x will do move semantics.

像极了他 2024-10-25 07:45:26

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

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

I wasn't 100% sure, but NO (thanks to the commentators) :

#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
}

output (with LOCAL_FUN):

default ctor
copy ctor
returning
1

Edit: Some more playing with the code led me to some fun with the local variables (LOCAL_FUN). So a really bad compiler that does not optimize copying, can actually break this code...

遗弃M 2024-10-25 07:45:26

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

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

Yes it will involve a copy of the container, but don't use void Foo( std::vector< std::string >* string_list );. Use void foo( vector<string>& string_list); instead.

Or just switch to C++0x and use a compiler that has already move optimizations implemented in the library.

呆头 2024-10-25 07:45:26

首先要求编译器消除复制构造,如果不能,则移动,如果不能则复制。因此,如果您的编译器非常糟糕,您可能会面临额外副本的开销。有关详细信息,请参阅此讨论

First compiler is required to elide copy construction, if can't, then move, if can't then copy. So if you have a really bad compiler, you risk incurring an overhead of an extra copy. See this discussion for details.

ゝ偶尔ゞ 2024-10-25 07:45:26

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

It depends on the copy constructor of the container. C++ has pass by value semantics. So when you return a vector for function Foo() it will be returned using value semantics i.e. a copy constructor will be invoked to copy the value of the vector. In this case the copy constructor of std::vector creates a new container and copies the values. In case of passing a pointer to the container you would have to allocate the memory if you have not allocated it already so the pointer points to an actual container and not a null value. From a programming practice perspective this is not a good thing to do because you leave the semantics open to interpretation. Better idea would be to pass a reference to the container and let the function fill the container with the desired elements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文