右值的函数重载

Function overloading for rvalue

我正在为二叉搜索树 class 实现一个 insert 函数,该函数有两个版本,一个使用左值项(要插入到tree) 和一个右值的树,我正在使用 std::move.

第一个:

template <typename Comparable>
void BinarySearchTree<Comparable>::insert(const Comparable &x, BinaryNode* &t)
{
    if (t == nullptr)
        t = new BinaryNode(x, nullptr, nullptr);

    if (x < t->element)
        insert(x, t->left);
    if (x > t->element)
        insert(x, t->right);
}

第二个:

template <typename Comparable>
void BinarySearchTree<Comparable>::insert(Comparable &&x, BinaryNode* &t)
{
    if (t == nullptr)
        t = new BinaryNode(std::move(x), nullptr, nullptr);

    if (x < t->element)
        insert(x, t->left); // should this be insert(std::move(x), t->left)?
    if (x > t->element)
        insert(x, t->right); // also here?
}

第二个函数中insert的递归调用应该用x还是std::move(x)调用?

我猜它应该是 x,因为它已经是一个右值,不需要 move(),但是,我使用的指南实现使用了 std::move()

首先,考虑一下标准对那些可以移动的对象的规定:

[...] moved-from objects shall be placed in a valid but unspecified state.

您不能指望它也适用于所有用户定义的类型,但这是一种常见模式。
让我们假设 Comparable 的情况并分析您的第二个函数:

template <typename Comparable>
void BinarySearchTree<Comparable>::insert(Comparable &&x, BinaryNode* &t)
{
    if (t == nullptr)
        t = new BinaryNode(std::move(x), nullptr, nullptr);

    if (x < t->element)
        insert(x, t->left); // should this be insert(std::move(x), t->left)?
    if (x > t->element)
        insert(x, t->right); // also here?
}

如果 t 等于 nullptr,您将 x 移动到 t
在该操作之后,x 可能会 处于有效但未指定的状态
这意味着 x < t->elementx > t->element 具有未定义的行为。
换句话说,一旦您将对象移出,您就不应该再使用它。同样,你不应该移动同一个物体两次。

Should the recursive call of insert in the second function be called with x or std::move(x)?

您可以简单地重写如下:

template <typename Comparable>
void BinarySearchTree<Comparable>::insert(Comparable &&x, BinaryNode* &t)
{
    if (t == nullptr) {
        t = new BinaryNode(std::move(x), nullptr, nullptr);
    } else if (x < t->element) {
        insert(std::move(x), t->left);
    } else if (x > t->element) {
        insert(std::move(x), t->right);
    }
}

只移动一次Comparable