C++链表移动赋值和移动构造函数
Posted
技术标签:
【中文标题】C++链表移动赋值和移动构造函数【英文标题】:C++ Linked List Move Assignment and Move Constructor 【发布时间】:2021-05-31 13:40:49 【问题描述】:我正在为我的面向对象编程课程编写一个单链表的实现。在程序中,我编写了一个名为Polynomial
的类,它实现了链表并允许我对其进行修改。链表中的节点包含两个字段:术语和指向下一个节点的指针。该术语是一个包含两个字段的结构:系数和指数。
到目前为止,我已经正确实现了该类及其方法,但是我在项目中遇到了一个需要帮助的问题。其中一个要求是我们实现了一个移动分配(?)和一个移动构造函数。不幸的是,我们的老师没有详细说明这些是什么或如何实施它们,现在我完全迷失了。我已经实现了 Copy Assignment 和 Copy Constructor,但是我不知道如何实现 Move Assignment 和 Move Constructor。
这是课程:
class Polynomial
Node* Head;
int size = 0;
public:
Polynomial(); // default constructor
Polynomial(const Polynomial& v); // copy constructor
~Polynomial();
void addTerm(Term term);
unsigned int degree() const;
double coefficientFor(unsigned int exponent) const;
void clear();
// Copy Assignment Operator
Polynomial& operator=(const Polynomial& rhs);
private:
void DeleteInvalidNode();
;
有什么方法可以帮助我实现这个实现以及它的目的是什么?
【问题讨论】:
【参考方案1】:假设你想复制一个多项式从一个地方到另一个地方。例如,您可能想要编写一个方法,让我们对多项式进行某种幂运算。 (假设您已经编写了乘法运算符的重载)。这可能看起来像这样 [1]
Polynomial Polynomial::pow(int n) const
Polynomial result = *this; // copy constructor
for(int i = 2; i < n; i++) result = result * *this;
return result;
当您将*this
分配给第一行中的result
时,制作一个副本 很重要,否则您可能会在尝试修改*this
时对其进行修改result
.
另一方面,假设您稍后使用此方法如下[2]:
Polynomial s;
// ...
s = p.pow(3); // move-assignment
p.pow(3)
的结果是一个多项式,但这里没有必要将 s
和 p.pow(3)
保留为单独的对象,因为我们无法在后面的任何点引用称为 p.pow(3)
的对象代码。
因此,我们不需要小心在这里复制;如果有某种方法可以传输p.pow(3)
返回的对象,而无需仔细复制它的每一部分,那么我们很好。
我们这样声明这个方法:
class Polynomial
// ...
/** Move constructor */
Polynomial(Polynomial &&);
/** Move-assignment operator */
Polynomial& operator=(Polynomial &&);
;
在这种情况下,由于您的多项式由链表表示,因此复制 Head
指针就足够了,然后对要移动的对象执行任何您需要的操作,以确保其析构函数不会t 销毁链表节点。这将取决于您如何编写所有内容,但可能您可以通过设置您已移动到 nullptr
的东西的 Head
指针等方法摆脱困境。
(当然记得在编写赋值运算符来清理 LHS 上需要清理的任何内容时!)
在您从某物移动构造或移动分配之后,您移动的对象被允许处于除了析构函数之外,它的任何功能都不能正常工作的状态;它不打算进一步使用。例如在上面s = p.pow(3)
的例子中,如果多项式有一个移动赋值运算符,那么它将被调用以将返回值移动到s
,然后将在返回值上调用析构函数。
[1] 这实际上不是编写此方法的最佳方式,但它为我提供了一个快速且有些相关的示例,因此我将使用它运行。
[2] 这里有一点微妙之处,解释了为什么我把它写成两行。如果我写Polynomial s = p.pow(3)
它实际上会通过复制省略 绕过所有这些,基本上告诉Polynomial::pow
直接使用s
作为它的返回值。复制和移动分配仅在您分配给以前具有不同值的东西时才真正使用。
【讨论】:
以上是关于C++链表移动赋值和移动构造函数的主要内容,如果未能解决你的问题,请参考以下文章
c++复习笔记——右值引用(概念,使用场景),移动拷贝构造函数,赋值拷贝构造函数。