简体   繁体   中英

How to use *this from inside a class member function to swap its own address with the address of a passed pointer (of same type)

Okay, here is a class named dLinikedList (yeah yeah, I know I should use STL containers):

class dLinkedList
{
public:

    //constructors will go here
    explicit dLinkedList(const int value)
    {
        createFirstNode(value);
        nodeCount = new size_t;
        updateNodeCount();
    }
    
    dLinkedList(const dLinkedList &rhs)
    {
        Node *temp = rhs.head;

        createFirstNode(temp->data);
        nodeCount = new size_t;
        updateNodeCount();
        
        temp = temp->next;
        while(temp)
        {
            push_back(temp->data);
            temp = temp->next;
        }
        
        updateNodeCount();
    }
    
    explicit dLinkedList(size_t numberOfNode, int initializationValue)
    {
        createFirstNode(initializationValue);
        for(size_t i = 1; i < numberOfNode; ++i)
            push_back(initializationValue);
        
        nodeCount = new size_t;
        updateNodeCount();
    }

    //class destructor will go here
    ~dLinkedList()
    {
        clear();
        delete nodeCount;
        nodeCount = nullptr;
    }

    //member functions will go here
    void push_back(int);                    // will attach a new node at the end of the list
    void push_front(int);                   // will insert a new node at the beginning of the list
    bool insertNode(int, int, bool, bool);  // will insert a new node after the existing node (true = first occurrence from the head with value int OTHERWISE if false, then from the tail.)
    bool deleteNode(int, bool);             // will delete the existing node (true = first occurrence from the head with value int OTHERWISE if false, then from the tail.)
    void pop_back();                         // will delete the last node in the list and return the value of the internal data
    void pop_front();                       // will delete the first node in the list
    size_t size();                          // will return the number of nodes/elements - experimental feature
    void printList(bool);                   // will print the values of the data - (true for ordered list, false for reverse ordered list)
    void swap(dLinkedList &rhs);             // will swap this linked-list with rhs

    //operator overloading go here
    dLinkedList& operator = (const dLinkedList &rhs);
    dLinkedList& operator + (const dLinkedList &rhs);
    dLinkedList& operator += (const dLinkedList &rhs);
    dLinkedList& operator >> (const size_t numberOfNodes);
    dLinkedList& operator << (const dLinkedList &rhs);

private:
    //defining the double linked-list structure
    struct Node
    {
        int data; //this is a generic place holder - will be replaced later with some actual data-structures
        Node *next;
        Node *previous;

        explicit Node(int x) : data(x), next(nullptr), previous(nullptr) {}
    };

    //member functions go here
    void createFirstNode(int val);  //will create the first node when the list is empty
    void clear();  // will be called when class destructor is called
    void updateNodeCount(); // keeps the nodeCount variable up-to-date
    bool empty(); // returns true if the list is empty

    //some experimental utility functions for internal use
    void ectomizeAndClip(Node*);
    Node *detectData(int, bool);
    void insertBefore(Node*, int);
    void insertAfter(Node*, int);

    //member variables go here
    Node *head {nullptr};
    Node *tail {nullptr};
    size_t *nodeCount {nullptr}; //experimental feature
    
};

There is this member function, currently implemented as:

void dLinkedList::swap(dLinkedList &rhs)
{
    dLinkedList temp {rhs};
    rhs.clear();
    
    Node *traverser = head;
    while(traverser != nullptr)
    {
        rhs.push_back(traverser->data);
        traverser = traverser->next;
    }
    
    clear();
    traverser = temp.head;
    while(traverser != nullptr)
    {
        push_back(traverser->data);
        traverser = traverser->next;
    }
}

Obviously, as the length of the list grows, this operation takes significant amount of time. Here is what I am thinking (if at all possible - in order to minimize the time to execute in cases of larger lists):

void dLinkedList::swap(dLinkedList *rhs)
{
// what I am planning to achieve is simply swap the address mutually.
    dLinkedList *temp {rhs};
    rhs = this;
    this = temp;
}

But this code is not working and is giving an error as follows:

error: lvalue required as left operand of assignment|

I want to clear my doubts/misconception about whether this is achievable? If yes, what will be the code.

this is a constant/immutable pointer dLinkedList* const this and can not be modified by this = temp .

Use the standard swap

void dLinkedList::swap(dLinkedList *rhs)
{
  std::swap(*this, *rhs);
}

The function parameter is rather incorrect and should be

void dLinkedList::swap(dLinkedList &rhs)
{
  std::swap(*this, rhs);
}

Your class consists of three pointers, just swap those pointers. This is very efficient and doesn't depend on the size of the list.

Like this

void dLinkedList::swap(dLinkedList &rhs)
{
    std::swap(head, rhs.head);
    std::swap(tail, rhs.tail);
    std::swap(nodeCount, rhs.nodeCount);
}

Sometimes this approach won't work if the nodes contain pointers back to the containing object, but that isn't the case here.

You can get the dLinkedList you want to swap as a reference in swap function and just swap the head s of this and rhs using std::swap .

void dLinkedList::swap(dLinkedList& rhs) {
    std::swap(this->head, rhs.head);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM