1

我正在创建一个无向图,每次我将邻居 A 添加到节点 BI 时,都必须将节点 B 添加为 A 的邻居,但我的方法不起作用。

Non-const lvalue reference to type 'Element *' cannot bind to a temporary of type 'Element *'

class Element
{
    std::vector<Element *> m_neighbours;
private:

public:
    void addNeighbour(Element*& neighbour)
    {
        m_neighbours.push_back(neighbour);
        neighbour->addNeighbour(this);
    }
};
  1. 怎么了?
  2. 最好的解决方法?
4

2 回答 2

1

this指针被定义为 prvalue ,并且您的函数采用lvalue. 由于各种原因,该语言禁止这种绑定。您没有修改给定的指针,因此只需按值而不是按引用传递它。

void addNeighbour(Element* neighbour);

代替

void addNeighbour(Element*& neighbour);
于 2020-04-06T18:26:55.847 回答
1

要了解问题所在,让我们假设您编写了以下代码:

void addNeighbour(Element*& neighbour)
{
    m_neighbours.emplace_back(neighbour);
    neighbour->addNeighbour(this);
    neighbour = nullptr; // <--- This is new
}

现在,想一想当你拨打这个电话时会发生什么:

neighbour->addNeighbour(this);

对函数的调用this通过引用传入,意思是“请随意重新分配this”。然后在函数调用中,最后一行确实尝试重新分配neighbournullptr. 但这是个问题,因为你不会写

this = nullptr; // Error!

因为this是一个右值。

这里最简单的解决方法是不通过引用获取参数,因为在实际需要引用的地方你没有做任何事情。只需接受一个Element*,说“请给我一份你感兴趣的指针的副本”。

(独立地 - 你的代码会给你带来麻烦,因为调用A->addNeighbour(B)会调用B->addNeighbour(A),哪些调用A->addNeighbour(B),哪些调用B->addNeighbour(A)等等,直到你把你的调用堆栈炸毁。你应该在这里添加一个检查以确保,如果Element已经记录,你不要第二次添加它。为此,您可能想要制作m_neighboursastd::unordered_set而不是 a std::vector。)

于 2020-04-06T18:25:06.293 回答