我有一个用户定义的类(树结构),带有实现的移动语义和swap
函数。我想以正确的方式实现move
函数,作为标准的std :: move实现。
在树节点类中,每个子节点都有一个parent
指针,指向父节点。这意味着对于移动操作,所有儿童都必须重新定位(并且可能有许多孩子)
这意味着使用swap
进行移动并不是最佳选择,因为两个列表的子项在交换后都必须重新分配。所以我想实现一个move
函数来清除移动的树。
std :: move实现的声明有点复杂,它们使用std::remove_reference<T>::type&&
返回类型。我需要这个吗?
答案 0 :(得分:6)
您不需要编写std :: move的专业化。
如果您编写了正确的移动构造函数并移动赋值运算符,则std :: move将适用于您的类。
示例:
#include <iostream>
#include <cstring>
using namespace std;
struct Thing {
Thing()
: _data(new int[100])
{
cout << "default construct\n";
}
// Copy operator
Thing(const Thing& other)
: _data(new int[100])
{
cout << "copy constructor\n";
memcpy(_data, other._data, sizeof(int) * 100);
}
// Move constructor
Thing(Thing&& other) noexcept
: _data(other._data)
{
cout << "move constructor\n";
other._data = nullptr;
}
// assignment operator
Thing& operator=(const Thing& rhs) {
cout << "copy operator\n";
if (&rhs != this) {
Thing tmp(rhs);
std::swap(*this, tmp);
}
return *this;
}
// move assignment operator
Thing& operator=(Thing&& rhs) noexcept {
cout << "move operator\n";
std::swap(_data, rhs._data);
return *this;
}
// destructor necessary since we are working in dangerous new/delete territory
~Thing() noexcept {
cout << "destructor " << (_data ? "object has data" : "object is empty") << "\n";
delete[] _data;
}
private:
int* _data;
};
int main()
{
cout << "constructing a\n";
Thing a;
cout << "constructing b with copy of a\n";
Thing b(a);
cout << "moving a to newly constructed c\n";
Thing c(std::move(a));
cout << "moving c back to a\n";
a = std::move(c);
cout << "create a new d\n";
Thing d;
cout << "replace d with a copy of a\n";
d = a;
return 0;
}
节目的输出:
constructing a
default construct
constructing b with copy of a
copy constructor
moving a to newly constructed c
move constructor
moving c back to a
move operator
create a new d
default construct
replace d with a copy of a
copy operator
copy constructor
move constructor
move operator
move operator
destructor object is empty
destructor object has data
destructor object has data
destructor object is empty
destructor object has data
destructor object has data
答案 1 :(得分:2)
写移动语义是写移动构造函数/移动赋值,而不是实现移动函数。因此,您可以在移动ctor / assignment中移动另一棵树的根。
class binary_tree_node {};
class binary_tree
{
public:
binary_tree() : root(nullptr) {}
binary_tree(binary_tree &&rhs)
: root(rhs.root)
{
rhs.root = nullptr;
}
binary_tree& operator=(binary_tree rhs)
{
swap(rhs);
return *this;
}
void swap(binary_tree &rhs)
{
std::swap(root, rhs.root);
}
private:
binary_tree_node *root;
};
int main()
{
binary_tree tree1;
binary_tree tree2 = std::move(tree1);
return 0;
}