首页 > 解决方案 > 将智能指针所有权转移到容器

问题描述

我有通常通过 管理的数据结构,std::unique_ptr例如 AST 中的表达式。

struct BinExpr {
 std::unique_ptr<Expr> left;    // Left owns the expression
 std::unique_ptr<Expr> right;   // Right owns the expression
};

在大多数情况下效果很好。

但有时我没有固定数量的表达式来拥有,例如在列表中

struct ListExpr {
  std::vector<std::unique_ptr<Expr>> exprs; // Exprs owns pointers which each own an expression 
};

但我不喜欢通过向量中的智能指针进行的这种额外间接,我认为它没有表达我想要的语义。
我认为向量应该拥有表达式,而不是拥有表达式的智能指针。

但我有一个问题,表达式总是在智能指针(或至少作为原始指针)中创建:

std::unique_ptr<Expr> parse_expr() { ... }

有没有一种优雅的方法可以将所有权从parse_expr调用(类型std::unique_ptr<Expr>为 a )转移std::vector<Expr>?当然Expr,这样做时不能复制。像

std::vector<Expr> exprs;
exprs.push_back(move_from_ptr_to_vec(parse_expr()));

所以基本上,目前我像这样使用它们

std::vector<std::unique_ptr<Expr>> exprs;
exprs.push_back(std::move(parse_expr()));
return std::unique_ptr<ListExpr>(exprs);   // List has a std::vector<std::unique_ptr<Expr>>

但我想要那样

std::vector<Expr> exprs;
exprs.push_back(parse_expr());
return std::unique_ptr<ListExpr>(exprs);   // List has a std::vector<Expr>

标签: c++containerssmart-pointers

解决方案


std::vector<Expr> exprs;
exprs.push_back(parse_expr());

不起作用,因为parse_expr()返回一个智能指针。您必须通过指针间接获取指向的对象:

exprs.push_back(*parse_expr());

Expr这样做时不得复制。

然后移动,假设没问题:

exprs.push_back(std::move(*parse_expr()));

但是,首先考虑一下为什么它们的表达式是动态分配的。据推测,它们是指向多态基础子对象的指针。在这种情况下,从基础移动可能对您没有用,基础对象数组的整个概念可能是错误的。

Expr可以是基类

在这种情况下std::vector<std::unique_ptr<Expr>>,这就是您所需要的。


推荐阅读