返回vector<Foo>还是shared_ptr<vector<Foo>>?

5
在一个函数中,哪个"return"更加合适?
A. vector<Foo> ?
B. shared_ptr<vector<Foor>> ?
换句话说,哪个拷贝更轻量级,你会选择哪个,并解释原因?

可能是重复/相关问题:https://dev59.com/bnA65IYBdhLWcg3wogAb - larsmoa
1
检查你的编译器,但通常可以假设省略会发生,在这种情况下,按值返回是最快的方法。这也是语义上最好的方式(幂等性、const结果赋值等),请参见此文章 - spraff
为什么不使用unique_ptr呢?返回shared_ptr意味着函数正在保留副本;而返回unique_ptr则让每个人都知道所有权已完全转移。 - Nicol Bolas
@NicolBolas unique_ptr也是一种选择,intrusive_ptr等也是如此。同样的问题。问题是是否应该使用智能指针。 - Alon Amir
3个回答

6
我认为很少有用处需要返回shared_ptr<vector<T>>。只有当多个对象需要持有一个共享的可操作向量时才会这样做。对我来说,这表明设计存在缺陷。更好的选择可能是通过const引用返回。这避免了(潜在昂贵的)复制操作,但不允许访问器改变向量。
如果您正在返回本地std::vector,您也可以通过参数返回它。
如果您确实想返回shared_ptr<vector<T>>,请考虑是否使用shared_ptr<const vector<T>>可以胜任工作(向量可以被许多人检查,但仅由所有者操作)。
然而,A通常比B更昂贵,但是此处通常适用于返回值优化。对于C++11,std::vector具有移动构造函数,将保证返回本地std::vector不需要昂贵的复制操作。
记住,不要过早优化 :)

所有这些都忽略了RVO / NRVO,这使得问题首先无意义。 - ildjarn

2

返回 shared_ptr<vector<Foo>> 可以确保不会发生额外的复制。

如果启用了返回值优化(RVO)或使用了C++11中的移动语义,返回 vector<Foo> 可能会避免额外的复制。但是,如果重要的是要避免复制,我不会使用这种方法(即使您可以确保这些优化将始终可用),因为我认为在实际上意味着不复制时使用返回副本语义并不是一个好主意。

我可能会选择以下其中一种,但这取决于情况:

  • vector<Foo> 的引用作为参数传递
  • 传递插入迭代器(例如 back_inserter

关于引用:是的,因为它将在函数作用域结束时被销毁。我正在不同平台上进行交叉编译,包括使用xCode的iOS和VS2010。你推荐哪一个? - Alon Amir
@AlonAmir 请查看更新后的答案。如果避免复制很重要,请不要按值传递 vector - hamstergene
5
如果这个函数会在内部创建 vector<Foo>,那我不会把它作为参数传递。对于我所知的所有编译器来说,如果返回类型不能放在寄存器中,调用约定将帮助你实现:调用者分配空间并将指针传递给被调用者,然后被调用者使用一个真实的对象来初始化该内存(根据代码调用适当的构造函数)。效果是你可以得到一个更干净的接口,而成本完全相同。 - David Rodríguez - dribeas
@DavidRodríguez-dribeas 对的,那正是我试图避免的,制作接收“out”参数的函数。 - Alon Amir

1

在C++03中,建议:

  1. 如果提供成员访问权限,请通过const引用返回。
  2. 否则,如果返回本地变量,请使用输出引用参数。

在C++11中,建议:

  1. 如果提供成员访问权限,请通过const引用返回。
  2. 否则,如果返回本地变量,请通过值返回,因为移动构造将避免过多的复制。

您希望返回引用计数智能指针的情况是多个具有不同生命周期的对象都想要访问该对象的情况。然而,这并不是最常见的情况,但它经常发生。


我不同意前两个建议。复制省略(Copy elision)/返回值优化(RVO)/无论他们想叫什么,都可以使得容器的返回变得更加便宜。而且,除非你返回一个临时对象,否则移动构造函数只有在你通过 std::move 显式地请求它们时才会被调用。无论如何,使用复制省略都是更好的选择。 - Nicol Bolas
C++03:永远不要返回对局部变量的引用。 - Barney Szabolcs
@BarnabasSzabolcs - 你应该更仔细地解析我的语言。如果你要返回的东西是函数内部的本地变量,那么请将对象的实例作为参数通过引用传递进来。 - Michael Price

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接