[英]performing deep copy in copy constructor
我有一個這樣定義的類棧:
#ifndef STACK_H
#define STACK_H
#include "MyException.h"
#include <iostream>
using namespace std;
template<class T>
class Stack;
template<class T>
ostream& operator<<(ostream&,Stack<T>&);
template<class T>
class Stack
{
public:
friend ostream& operator<< <T>(ostream&,Stack<T>&);
/*The constructor for the Stack class*/
Stack();
/*The copy constructor*/
Stack(const Stack<T>& other);
Stack<T>& operator=(const Stack<T>& other);
/*The destructor for the stack class*/
~Stack();
void push(const T& el);
T pop();
bool isEmpty();
private:
/*The node class.*/
class Node
{
public:
Node(const T& data, Node* n = 0)
{
element = data;
next = n;
}
T element;
Node* next;
};
/*The top of the stack*/
Node* top;
};
#include "Stack.C"
#endif
而且我必須在副本構造函數中執行深層復制。 但是我要做的是創建一個臨時數組,然后將參數接收到的對象中的所有元素復制到數組中,然后將節點復制到數組中,然后將所有元素推入Stack類中定義的節點中。 這是我的方法:
template<class T>
Stack<T>::Stack(const Stack<T>& other)
{
top = NULL;
if(other.top == NULL)
{
this->top=NULL;
}
else
{
Node* count;
count= other.top;
int num=1;
while(count->next != NULL)
{
num++;
count = count->next;
}
cout<<"test"<<endl;
T arr[num];
arr[0] = other.top->element;
Node* count2;
count2= other.top;
for(int i = 1 ; i<num; i++)
{
arr[i] = count2->next->element;
count2 = count2->next;
}
T temp;
for(int i =0, j=num-1; i<num/2 ; i++, j--)
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
for(int i =0; i<num; i++)
{
push(arr[i]);
cout<<arr[i]<<endl;
}
}
}
您可以假設我的push(const T&el)和pop()正常工作。 誰能幫助我進行深度復制?
沒有理由使用數組來深度復制堆棧。 由於您擁有指向當前堆棧鏈中節點的所有指針,因此只需遍歷該鏈表即可。 該算法的不尋常部分包括在輸入新節點時將它們向前鏈接 ,從而保留原始堆棧順序。 有很多方法可以做到這一點,但是我更喜歡使用單個指針到指針,該指針始終保存將在下一個副本中填充的指針的地址 。
Stack(const Stack<T>& other)
: top(nullptr)
{
const Node* p = other.top;
Node **pp = ⊤
while (p)
{
*pp = new Node(*p);
p = p->next;
pp = &(*pp)->next;
}
*pp = nullptr;
}
完成此操作后,將對堆棧進行深拷貝復制並保留源對象的順序。 而且我強烈建議實現一個Node(const Node&)
copy-ctor,它僅復制數據元素並將下一個指針硬設置為null。
這個怎么運作
最后,這不過是前向鏈接列表的單掃描副本。 指針pp
始終保存將被分配新節點的下一個指針的地址。 重要的是要記住,要尋址的指針是列表的一部分 ,而不是某些臨時指針。 最初為pp
分配了頂部指針的地址,該指針恰巧已經初始化為NULL。 從那里開始,重復以下操作,直到耗盡節點為止:
*pp
。 這意味着由pp
尋址的指針將接收新的節點地址。 pp
可以保存剛分配的節點的next
成員的地址。 這成為下一次插入的下一個目標 重復此過程,直到節點用完為止。 那時pp
保留最后一個節點的next
指針的地址,應將其分配為null以便我們的列表正確終止。 這就是關閉*pp = nullptr;
的目的*pp = nullptr;
。 這樣,列表現在終止,並且該對象現在具有源對象的鏈接列表的副本。
一些思考的食物。 如果源列表最初為空,會發生什么? 可以與循環列表一起使用嗎(答案:否,甚至不要嘗試)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.