簡體   English   中英

在復制構造函數中執行深度復制

[英]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 = &top;
    while (p)
    {
        *pp = new Node(*p);
        p = p->next;
        pp = &(*pp)->next;
    }
    *pp = nullptr;
}

完成此操作后,將對堆棧進行深拷貝復制並保留源對象的順序。 而且我強烈建議實現一個Node(const Node&) copy-ctor,它復制數據元素並將下一個指針硬設置為null。

這個怎么運作

最后,這不過是前向鏈接列表的單掃描副本。 指針pp始終保存將被分配新節點的下一個指針的地址。 重要的是要記住,要尋址的指針是列表的一部分 ,而不是某些臨時指針。 最初為pp分配了頂部指針的地址,該指針恰巧已經初始化為NULL。 從那里開始,重復以下操作,直到耗盡節點為止:

  1. 將當前源節點的副本分配給*pp 這意味着由pp尋址的指針將接收新的節點地址。
  2. 前進pp可以保存剛分配的節點的next成員的地址。 這成為下一次插入的下一個目標
  3. 將源指針前進到下一個源節點。

重復此過程,直到節點用完為止。 那時pp保留最后一個節點的next指針的地址,應將其分配為null以便我們的列表正確終止。 這就是關閉*pp = nullptr;的目的*pp = nullptr; 這樣,列表現在終止,並且該對象現在具有源對象的鏈接列表的副本。

一些思考的食物。 如果源列表最初為空,會發生什么? 可以與循環列表一起使用嗎(答案:否,甚至不要嘗試)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM