右值的函数重载
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->element
和 x > 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
。
我正在为二叉搜索树 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->element
和 x > 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
。