Pat*_*ick 3 c++ constructor destructor linked-list copy-constructor
我有一个 C++ 代码:
#include <iostream>
using namespace std;
struct Node;
typedef Node *NodePtr;
struct Node
{
int Item;
NodePtr Next;
};
class LinkedList
{
public:
LinkedList(); // default constructor
~LinkedList(); // destructor
void AddTail(int); // adds item to tail
private:
NodePtr Head;
};
LinkedList::LinkedList()
{
Head = NULL; //declare head as null
}
//Adding on tail
void LinkedList::AddTail(int Item)
{
NodePtr Crnt;
NodePtr node = new Node;
node->Item = Item;
node->Next = NULL;
//if head is in null declare the added node as head
if (Head == NULL)
{
Head = node;
}
else
{ //set the current to head, move the current node to current next node
Crnt = Head;
while (Crnt->Next != NULL)
{
Crnt = Crnt->Next;
}
//Add item to the tail of the linked list
Crnt->Next = node;
}
}
int main()
{
LinkedList la;
la.AddTail(30);
la.AddTail(60);
la.AddTail(90);
LinkedList lb;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是如何实现一个复制构造函数(假设在对象 lb 上),该构造函数对列表参数进行深度复制,并添加用于在空和非空列表上测试复制构造函数的代码?提前致谢。
编程的重要规则之一是不要重复自己 (DRY)。如果您有一个添加函数并且您知道它有效,请继续将它用于与添加相关的作业。这意味着继续添加愚蠢和多才多艺的内容符合您的最佳利益。
应用 DRY 哲学,假设该AddTail方法正常工作,复制构造函数非常简单:调用AddTail源列表中的每个节点。
LinkedList::LinkedList(const LinkedList & src):Head(nullptr)
{
NodePtr node = src.Head;
while (node != nullptr)
{
AddTail(node->Item);
node = node->Next;
}
}
Run Code Online (Sandbox Code Playgroud)
多亏了Copy and Swap Idiom,拥有一个有效的复制构造函数使得赋值运算符也变得非常简单:
LinkedList & LinkedList::operator=(LinkedList src)
// pass by reference performs the copy
{
std::swap(Head, src.Head); // now just swap the head of the copy
// for the head of the source
return *this;
} // destructor fires for src and cleans up all the nodes that were on this list
Run Code Online (Sandbox Code Playgroud)
为了完成三重奏规则,我们需要一个析构函数。这就像复制构造函数是 DRY 的应用程序:一遍又一遍地调用您的节点删除函数,直到列表为空。删除函数几乎是任何链表的必然要求,所以这里我假设有一个名为Remove.
LinkedList::~LinkedList()
{
while (Head != nullptr)
{
NodePtr temp = Head;
Remove(Head);
delete temp;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,现在基于链表在没有任何情况下无法运行的两个功能,我们已经实现了基本维护所需的所有其他功能。您所需要的一切都经过测试,没有错误Add和Remove功能,其余的几乎免费。
并且因为该AddTail函数命中了我的一个宠物豌豆......这里有一个可以大大降低函数复杂度的技巧:
void LinkedList::AddTail(int Item)
{
NodePtr *Crnt = &Head; // instead of pointing where Head points, point at
// Head now we don't care if it is head or any
// other node's Next. They are all abstracted to
// the same thing: A pointer to where the next
// node can be found
while (*Crnt != NULL) // keep looking until end of list
{
Crnt = &(*Crnt)->Next; // by pointing at the next Next pointer
}
//Add item to the tail of the linked list
NodePtr node = new Node;
node->Item = Item;
node->Next = NULL;
*Crnt = node; // Now just plop the new node over top of the terminating NULL
}
Run Code Online (Sandbox Code Playgroud)
Remove我没有实现的函数使用相同的指针到指针技巧。