C++ 如何实现c++;11用户定义类的移动函数?
我有一个用户定义的类(树形结构),带有实现的移动语义,还有一个C++ 如何实现c++;11用户定义类的移动函数?,c++,c++11,move,move-semantics,C++,C++11,Move,Move Semantics,我有一个用户定义的类(树形结构),带有实现的移动语义,还有一个swap函数。我想以正确的方式实现一个move函数,作为标准的std::move实现 在树节点类中,每个子节点都有一个指向父节点的parent指针。这意味着对于移动操作,所有子项都必须重新租用(可能有许多子项) 这意味着使用swap进行移动不是最佳选择,因为两个列表的子列表在交换后都必须重新出租。因此,我想实现一个move函数来清除moved from树 std::move实现的声明有些复杂,它们使用std::remove\u ref
swap
函数。我想以正确的方式实现一个move
函数,作为标准的std::move实现
在树节点类中,每个子节点都有一个指向父节点的parent
指针。这意味着对于移动操作,所有子项都必须重新租用(可能有许多子项)
这意味着使用swap
进行移动不是最佳选择,因为两个列表的子列表在交换后都必须重新出租。因此,我想实现一个move
函数来清除moved from树
std::move实现的声明有些复杂,它们使用
std::remove\u reference::type&
返回类型。我需要这个吗?你不需要写std::move的专业文章
如果您编写了正确的move构造函数和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;
}
编写移动语义就是编写移动构造函数/移动赋值,而不是实现移动函数。所以,您可以在move-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;
}
这是非常不清楚的。单参数
std::move
只是一个强制转换,您无需实现任何功能。而且内部交换
通常在左值引用上运行。删除引用
非常简单。请看,如果编译器支持decltype(auto)
(一个C++14特性AFAIK)(请参阅大约6.5分钟后的内容),您可以稍微简化定义。我从std::move确实可以在标准容器上有效交换这一事实开始,我不希望这样。所以std::move只有在我的move-ctor/assignment进行交换时才会交换,而move-if-the-move?Makes sensestd::move只是将对象引用转换为R值引用,允许选择和对象的move构造函数或move运算符。我给你写一个小例子,好了。提供了一个例子。编译它,然后一步一步地完成。不要忘记noexcept
。许多标准库如果不能保证移动是不可丢弃的,就会退化为更安全的复制语义。从头开始编写指针控制类的完整实现是健康的-再次强调了为什么我们不应该这样做,因为要正确无误地进行操作非常困难,而std::unique_ptr
和std::shared_ptr
则可以完美安全地使用指针完成所有您想做的事情。
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;
}