我有一个长时间的调试会话(6小时以上)。我调试我的A *算法的实现。
检查所有的可能性,一步等添加日志,调试步骤之后后,我终于找到了答案。基本上,它归结于一个行,其中我搜索在载体中的最小值。
看一下这个:
auto open_set = std::vector<std::shared_ptr<node>>{start_node};
std::shared_ptr<node> current;
while (!open_set.empty())
{
current = *std::min_element(open_set.begin(), open_set.end());
该current = *std::min_element(open_set.begin(), open_set.end());
行本来是要找到一个向量的最低node
。这是我的node
实现:
class node
{
public:
node() : G(0), H(0) {}
node(const QPoint& p) : pos(p), G(0), H(0) {}
bool operator==(const node& o) const { return pos == o.pos;}
bool operator==(const QPoint& o) const { return pos == o; }
bool operator!=(const node& o) const { return pos != o.pos; }
bool operator<(const node& o) const { return G + H < o.G + o.H; }
QPoint pos;
std::shared_ptr<node> parent;
int G;
int H;
};
所以,我有需要寻找operator<
的min_element
。问题是,许多次后看我的日志我发现我曾与即G = 8 node
,H = 10,节点G = 10,H = 10。猜测哪个被选中作为min_element
- >第二!我不知道为什么,我很生气,所以我写了一个简单的lambda来比较节点:
current = *std::min_element(open_set.begin(), open_set.end(),
[&] (const std::shared_ptr<node>& lhs, const std::shared_ptr<node>& rhs)
{
return lhs->G + lhs->H < rhs->G + rhs->H;
});
和繁荣,这一点:
改成这样:
很明显,你可以看到,第一个是错误的。我查了很多次,这很管用了,所以这个问题是真的在这里。
所以在这里我的问题是,为什么当我使用std::min_element
没有它的工作。是否有做的其实我有std::vector
s的std::shared_ptr<node>
而不是仅仅node
s的东西吗?我必须用operator<
类写node
不同?
C ++的文档为什么这个问题是发生很清楚:
如果你看一下在shared_ptr的页面:
https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_cmp
需要注意的是比较运营商的shared_ptr只比较指针值;实际的对象指向没有比较。具有操作者<用于shared_ptr的定义允许shared_ptrs被用作关联容器键,比如std ::地图和std ::设置。
但有办法让的std ::分钟达到你想要的行为。你可以实现一个比较函数对象或使用lambda像你已经离开。
class node
{
public:
node() : G(0), H(0) {}
node(int x, int y) : G(x), H(y) {}
bool operator<(const node& o) const { return (G + H) < (o.G + o.H); }
int G;
int H;
};
struct NodeComparer
{
bool operator()(std::shared_ptr<node> const& lhs, std::shared_ptr<node> const& rhs) const
{
return *lhs < *rhs;
}
};
int main()
{
std::shared_ptr<node> a = std::make_shared<node>(3, 6);
std::shared_ptr<node> b = std::make_shared<node>(1, 1);
std::shared_ptr<node> c = std::make_shared<node>(2, 2);
auto open_set = std::vector<std::shared_ptr<node>>
{
a,b,c
};
std::shared_ptr<node> current;
current = *std::min_element(open_set.begin(), open_set.end(), NodeComparer());
getchar();
}
只要你在shared_ptr的包节点了,你不再处理节点类型,你正在处理的shared_ptr的类型。所以,你应该预料到你对数据做操作都将反映这一点。例如情况下,sizeof()运算符应用于一个shared_ptr节点会还给你一个shared_ptr不是一个节点的尺寸大小。以同样的方式,当你在两个shared_ptr的公司做一个比较这是该类型定义的shared_ptr的比较操作。