从函数返回一个 unique_ptr 向量

Posted

技术标签:

【中文标题】从函数返回一个 unique_ptr 向量【英文标题】:Returning a vector of unique_ptr from function 【发布时间】:2012-08-31 10:15:32 【问题描述】:

我目前正在阅读《Head First Object Oriented Analysis and Design》一书,同时也习惯了 C++11 的一些特性(尤其是 unique_ptr 和 move 语义)。在书中,他们以策略棋盘游戏的设计为例。它有一个板,瓷砖和瓷砖上的单位。代码是用 Java 编写的,我试图用 C++ 重写它。在Java中,tile类如下:

public class Tile

    private List units;

    public Tile()
    
        units = new LinkedList();
    

    protected void addUnit(Unit unit)
    
        units.add(unit);
    

    protected List getUnits()
    
        return units;
    

我首先在 c++ 中使用 shared_ptr 做了同样的事情。与我使用原始指针的第二个版本相比,它工作但非常慢。然后我尝试了 unique_ptr:

class Tile


public:
  Tile();
  virtual ~Tile();

  void addUnit()
  
    mUnits.push_back(std::unique_ptr<Unit>(new Unit());
  

  std::vector<std::unique_ptr<Unit>> getUnits()
  
    return mUnits;
  

private:
  std::vector<std::unique_ptr<Unit>> mUnits;

;

编译器不喜欢 getUnits。据我了解,它来自于复制构造函数在 unique_ptr 中被禁用的事实。你将如何返回向量列表? 谢谢!

【问题讨论】:

引用返回:std::vector&lt;std::unique_ptr&lt;Unit&gt;&gt;&amp; getUnits() 返回一个 unique_ptrs 向量意味着放弃它们,因此 Tile 不再可以访问它们。这就是你想要的吗? 你真的需要返回向量吗?如果你的类包装了std::vector,你应该提供比这个访问器更好的对其数据的访问。这个例子清楚地表明,从 Java 到 C++ 的不费吹灰之力的重写不是要走的路。尤其是因为您没有提供任何新功能。 别忘了,Java“对象”是指针;即使看起来像按值返回,结果也指向原始对象。 C++ 中的类比是返回一个指针或引用。 原来的类无论如何设计都很糟糕,希望那本书能提到这一点。为什么封装一个容器只是为了提供对它的完全访问权限? 【参考方案1】:

在 C++ 中返回的值会产生一个副本 - 如果这是您想要的,您不能使用 unique_ptr 或必须手动复制和 std::move 它。但是,我认为您只想提供对Units 的访问权限(无论出于何种原因......),所以只需返回一个引用:

std::vector<std::unique_ptr<Unit>> const& getUnits() const

  return mUnits;

const 仅在您不想授予向量写入权限时才需要。)

现在,仍然有几个问题出现:为什么是~Tile virtual?我看没必要。

你为什么使用 owning ptr 来指向单位?在原始 Java 代码中,您获得了对外部单元的引用,并且只存储了一个引用 - 如果 Java 代码中的 Tile 被破坏,则单元不会(据我所见),只要它们是在别处引用。为了在 C++ 中实现完全相同,您使用 shared_ptr 是正确的。

当然,您可以明确 是单位的真正所有者并进行相应操作 - 如果它不是 Tile,请使用原始指针。另见"Which kind of pointer do I use when?"

【讨论】:

~Tile() 是虚拟的,因为 Java 代码具有 protected 方法,这意味着其目的是从该方法派生类。 Funny... 我尝试了 auto test = getUnits() 但我收到一个错误:“使用已删除的函数 'std::unique_ptr 等 :-( @darkman:嗯..auto x = init; 会导致复制发生。使用auto&amp; x = init; 为什么这在 Visual Studio 2013 中不起作用?我仍然在尝试访问复制构造函数时遇到编译器错误... 在 "auto& x = init;" 中,Xeo 在 auto 之后使用 & 来指定 x 是对 init 的左值引用。点击此处了解更多详情:open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html

以上是关于从函数返回一个 unique_ptr 向量的主要内容,如果未能解决你的问题,请参考以下文章

从函数返回 unique_ptr

提升(反)序列化派生对象的向量,使用已删除的函数(unique_ptr)

std::auto_ptr 在我的模板类中编译,但不是 std::unique_ptr

带有 unique_ptr 的双端队列向量的编译器错误

如何将唯一指针从一个向量移动到另一个唯一指针向量? [关闭]

duang!!!为什么函数能够返回unique_ptr