我正在创建一个双链表模板,我必须在传入链表的地方编写两个构造函数,然后构造一个新的列表,该列表具有相同数量的节点以及这些节点中相同的编号。节点的内存位置将是两者之间的唯一区别。
我有两个建设者。一种是接受List&
的复制构造函数和接受List&&
:的移动构造函数
List(const List &rhs);
List(List &&rhs);
现在我的问题是,两者的代码都是一样的,因为它不是一个肤浅的副本,对吧?区别仅用于汇编目的?我的理解是,我不需要std::move
来实现第二个构造函数。
第二个构造函数的目的是能够创建一个使用临时对象作为参数的列表,例如:L1 = L2+ L3
,其中L2+L3
变成了一个临时列表,一旦它被分配给L1
,就会被删除。
如果您只执行浅层复制,特别是非指针值(或任何其他已分配的资源(,则不需要移动构造函数。
两者的代码都是一样的,因为它不是一个浅拷贝,对吧?
List(const List &rhs)
复制构造函数应将数据(而非节点本身(从rhs
深度复制到this
,但在其他情况下保持rhs
不变。
List(List &&rhs)
移动构造函数应将节点本身从rhs
移动(窃取(到this
,并使rhs
处于空状态。
所以,不,他们不会使用相同的代码,甚至不会关闭。
移动赋值例如: 像 返回的operator=
复制赋值和template<typename T>
class List
{
private:
struct node
{
T data;
node *previous;
node *next;
};
node *head = nullptr;
node *tail = nullptr;
size_t size = 0;
public:
// default constructor
List() = default;
// copy constructor
List(const List &rhs)
{
node **newNode = &head;
for(node *curNode = rhs.head; curNode; curNode = curNode->next)
{
*newNode = new node{curNode->data, tail, nullptr};
tail = *newNode;
++size;
newNode = &(tail->next);
}
}
// move constructor
List(List &&rhs)
: head(rhs.head), tail(rhs.tail), size(rhs.size)
{
rhs.head = rhs.tail = nullptr;
rhs.size = 0;
}
// destructor
~List()
{
node *curNode = head;
while (curNode) {
node *next = curNode->next;
delete curNode;
curNode = next;
}
}
// copy assignment
List& operator=(const List &rhs)
{
if (this != &rhs) {
List tmp(rhs);
std::swap(head, tmp.head);
}
return *this;
}
// move assignment
List& operator=(List &&rhs)
{
List tmp(std::move(rhs));
std::swap(head, tmp.head);
return *this;
}
/*
Alternatively, you can use just 1 implementation of operator=
for both copy and move assignments, by taking the input parameter
*by value* and letting the compiler decide which constructor
to call to initialize it, based on the type of input being assigned:
// copy/move assignment
List& operator=(List rhs)
{
List tmp(std::move(rhs));
std::swap(head, tmp.head);
return *this;
}
*/
};
L1 = L2 + L3
这样的操作必须实现operator+
,它将2个List
对象作为输入,并返回一个新的List
对象,该对象具有从L2
和L3
复制的数据(而不是节点(,例如:template<typename T>
class List
{
...
public:
...
List& operator+=(const List &rhs)
{
if (rhs.head) {
List tmp(rhs);
node **ptr = (tail) ? &(tail->next) : &head;
*ptr = tmp.head; tmp.head = nullptr;
tail = tmp.tail; tmp.tail = nullptr;
size += tmp.size;
}
return *this;
}
// operator+ can be implemented either as a class member
// using *this as the left-hand operand...
List operator+(const List &rhs) const
{
List res(*this);
res += rhs;
return res;
}
};
// Or, operator+ can be implemented as a non-member function...
List operator+(const List &lhs, const List &rhs)
{
List res(lhs);
res += rhs;
return res;
}
List
将是一个临时对象,也称为右值,然后使用operator=(List&&)
移动赋值运算符(或使用List(List&&)
移构造函数的operator=(List)
赋值运算符(将其分配给L1
。