非 Const 左值引用

Posted

技术标签:

【中文标题】非 Const 左值引用【英文标题】:Nonconst lvalue reference 【发布时间】:2020-04-06 18:19:16 【问题描述】:

我正在创建一个无向图,每次我将邻居 A 添加到节点 B 时,我都必须将节点 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);
    
;
    发生了什么? 最好的解决方法?

【问题讨论】:

emplace_back 指针而不是 push_back 的动机是什么? 通过引用传递指针对我来说似乎也是一种代码味道,尤其是因为它在函数内没有改变。 我改了 但是如果我在理论上不通过引用传递它,我有一个副本,所以在调用 addNeighbour 时我不会调用真正的邻居不是吗? @HectorEstebanCabezos 您将拥有指针的副本,而不是被指向的东西的副本。 【参考方案1】:

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

void addNeighbour(Element*& neighbour)

    m_neighbours.emplace_back(neighbour);
    neighbour->addNeighbour(this);
    neighbour = nullptr; // <--- This is new

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

neighbour->addNeighbour(this);

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

this = nullptr; // Error!

因为this 是一个右值。

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

(独立 - 你的代码会给你带来麻烦,因为调用 A-&gt;addNeighbour(B) 将调用 B-&gt;addNeighbour(A),它调用 A-&gt;addNeighbour(B),它调用 B-&gt;addNeighbour(A),等等,直到你炸毁你的调用堆栈。你应该添加一个在此处检查以确保,如果 Element 已被记录,则不要再次添加它。为此,您可能希望将 m_neighbours 设为 std::unordered_set 而不是 std::vector。)

【讨论】:

当您尝试更改函数内部指针指向的内容时,您可能会引用它。尽管您也希望有充分的理由不只是使用退货。【参考方案2】:

this 指针 is defined to be a prvalue,而您的函数采用 lvalue。该语言禁止这种绑定for various reasons。您没有修改给定的指针,因此只需按值而不是按引用传递它。

void addNeighbour(Element* neighbour);

而不是

void addNeighbour(Element*& neighbour);

【讨论】:

以上是关于非 Const 左值引用的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 11 中将非 const 左值引用绑定到右值是不是有效?(修改)

非常量左值引用的示例

为啥我不能将 const 左值引用绑定到返回 T&& 的函数?

模板中右值引用和 const 左值引用之间的重载

为啥在特殊成员函数中将 r 值绑定到 const 左值引用是非法的?

C++ 非 const 右值参数解决方法