如何返回指针的向量(及所有权)C++11

15

我有一个工厂方法,它创建了一堆对象并返回指向它们的指针。这些对象的所有权会转移到调用方:

std::vector<animal*> create_zoo();

这样做虽然可行,但容易发生内存泄漏。

auto zoo = create_zoo();

这个向量是在栈上的,会自动清理,但是其中包含的对象不会。

返回各种子类型的对象。使用返回值而不是指针是不可行的。

我在考虑使用

std::vector<std::unique_ptr<animal> > create_zoo();

但是unique_ptr没有复制语义,并且我通过值返回vector,理论上会创建一份副本。

我可以将vector放在堆上以避免这个问题。

std::unique_ptr<std::vector<std::unique_ptr<animal> > > create_zoo();

但这已经变得荒谬了。

这也应该可以工作:

std::vector<std::shared_ptr<animal> > create_zoo();

这样做是可行的,但它并没有真正转移所有权。调用者必须假设可能存在指向这些对象的其他指针。

我接受建议。不一定需要使用 std::vector。我只是在寻找一种用现代C++实现返回多个对象所有权的好方法。目前避免使用boost库,我正在尝试探索新的C++11内容。


你还可以重新考虑是否需要将动物对象分配为指针。std::vector<animal>也可以满足您的需求。动物对象将与向量一起分配并在移动操作后移动。 - Erik Uggeldahl
1个回答

15

std::vector<std::unique_ptr<animal>> 可以正常工作:返回函数本地值将移动它,而不是复制它(或仅当移动不可用时才复制)。


嗯...这是否意味着我的代码取决于编译器执行“返回值优化”的能力?我知道所有相关的编译器都已经实现了它,但我不确定它们是否保证在所有情况下都执行它。这是标准做法吗? - Stefan
7
不,这不是RVO。RVO会完全删除函数本地变量,并在其位置上使用调用者侧的变量。这篇文章讨论的是通过return移动构造返回的临时对象(如果RVO之前失败)。 - Quentin
3
这正是我所缺失的一点!在6年使用Python后重新学习c++,我感到有些生疏又有些溺爱。我将去阅读关于“移动(move)”的资料。谢谢! - Stefan
@Quentin 技术上它将(或可以)省略函数局部变量,而不是删除它。 (在某些(标准描述的)情况下,省略是合法允许的合并对象标识的过程。所有对象都存在,但现在它们的名称(如果有)都指向具有一个组合生命周期的同一对象。) - Yakk - Adam Nevraumont
1
@Stefan 此外,在 C++17 中还将有所谓的“保证复制省略”,我相信这将强制实现类似于 RVO 的行为,即使没有移动或复制构造函数。 - Kyle Strand
@Yakk 感谢您提供高层次的视角。我陷入了解释实现细节的陷阱中 :) - Quentin

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