在赋值操作符中分配 std::shared_ptr

5

我正在为boost::filtered_graph创建自己的自定义过滤器类。WeightMap概念必须具有默认构造函数、复制构造函数和赋值运算符。

我创建了下面的类,它有一个std::shared_ptr私有成员。我的问题是如何编写赋值运算符。复制构造函数不是问题,但赋值运算符无法正常工作。

class BFDMFilter
{
private:
const BGraph* m_battlemap;
const std::shared_ptr<MoveAbility> m_mv_ab;

public:
BFDMFilter() : m_battlemap(nullptr), m_mv_ab() { }
BFDMFilter(const BGraph* bmap, std::shared_ptr<MoveAbility> mv) : m_battlemap(bmap), m_mv_ab(mv) { }

BFDMFilter(const BFDMFilter& filter) : m_battlemap(filter.m_battlemap), m_mv_ab(filter.m_mv_ab) { }
BFDMFilter& operator=(const BFDMFilter& filter) 
{
  if(this != &filter)
  {
m_battlemap = filter.m_battlemap;
m_mv_ab = filter.m_mv_ab;
  }

  return *this;
}

bool operator()(const Edge& edge) const 
{ 
  Tile::TileEdge path = (*m_battlemap)[edge];

  return m_mv_ab->CanMove(path.TerrainType()) > 0.0;
}

bool operator()(const Vertex& vertex) const 
{ 
  Tile tile = (*m_battlemap)[vertex];

  return m_mv_ab->CanMove(tile.TerrainType()) > 0.0;
}
};

然后就出现了编译错误:

error: passing ‘const std::shared_ptr<momme::battle::MoveAbility>’ as ‘this’ argument of ‘std::shared_ptr<_Tp>& std::shared_ptr<_Tp>::operator=(std::shared_ptr<_Tp>&&) [with _Tp = momme::battle::MoveAbility, std::shared_ptr<_Tp> = std::shared_ptr<momme::battle::MoveAbility>]’ discards qualifiers [-fpermissive]

我明白了,赋值运算符在执行赋值时会修改shared_ptr的引用计数,以便跟踪有多少个打开的引用。但问题是,我该如何编写赋值运算符呢?std :: weak_ptr也具有相同的行为,如果我将引用设为非const,则boost库会报错函数已被删除。


2
我不确定为什么你需要指针是const...你是指 std::shared_ptr<const MoveAbility> m_mv_ab 吗?你想让 std::shared_ptr 本身是const还是它所指向的对象是const? - Stephen Lin
1
你不能对任何 const 数据成员进行赋值。这不仅适用于 shared_ptr - juanchopanza
1个回答

12

从您的代码中看不出需要将 m_mv_ab 声明为什么类型。

const std::shared_ptr<MoveAbility> m_mv_ab;

这是智能指针版本的:

MoveAbility * const m_mv_ab;

(指向非常量 MoveAbility 的常量指针)

如果您不想修改所指向的 MoveAbility 对象并希望它是const,则应该这样做:

std::shared_ptr<const MoveAbility> m_mv_ab;

这是“智能指针版本”的意思:
const MoveAbility * m_mv_ab;

(非常量指针指向常量 MoveAbility

为了更加直观,您可以始终在末尾使用const后缀,并始终从右到左阅读,除了std :: shared_ptr<X>是“指向 X 的(智能)指针”:

std::shared_ptr<MoveAbility> const m_mv_ab; // const ptr to non-const MoveAbility
MoveAbility * const m_mv_ab; // const ptr to non-const MoveAbility

std::shared_ptr<MoveAbility const> m_mv_ab; // non-const ptr to const MoveAbility
MoveAbility const * m_mv_ab; // non-const ptr to const MoveAbility

但大多数人尽可能使用const作为前缀,这使得它很容易混淆。


1
真是个愚蠢的错误,我简直不敢相信我会错过那个。谢谢你指出来。 - Brad
@Brad 经常发生这种情况,这并不是很直观。 - Stephen Lin

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