Charo copy and deep copy questions.In the program below, why should the provisional argument of the append method be &otherList instead of otherList?

Asked 1 years ago, Updated 1 years ago, 322 views

We created a program that combines two consolidated lists (connecting one consolidated list to the other) and displaying the combined list.

Append(TextClass otherList) doesn't work, but it has to be append(TextClass const&otherList), but I don't know exactly why.Why doesn't append (TextClass otherList) work?

main.cpp

#include<iostream>
# include "TextClass.h"

using namespace std;

int main() {
    const int APPEND1 = 6;
    const int APPEND2 = 7;
    int counter = 0;
    char appendVals [APPEND1+APPEND2] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'};

    TextClass first;
    for (inti=0;i<APPEND1;i++)
    {
        first.addTail (appendVals [counter]);
        counter++;
    }
    TextClass second;
    for (inti=0;i<APPEND2;i++)
    {
        second.addTail(appendVals[counter]);
        counter++;
    }

    std::cout<<"First list is"<<first.displayList()<<std::endl;
    std::cout<<"Second list is"<<second.displayList()<<std::endl;

    first.append(second);
    std::cout<<"First should now be a bc de fghijklm"<<std::endl;
    std::cout<<"and it actually is"<<first.displayList()<<std::endl;

    std::cout<<"Done applying a list\n"<<std::endl;


    return 0;
}

TextClass.cpp

#include "TextClass.h"
# include <sstream>
// constructor
Link:: Link (charletter, Link*next, Link*prev)
{
    value = letter;
    this ->next=next;
    this ->prev=prev;
}

// destructor
Link::~Link(){}

// return the value in the link
char Link::getValue() {return value;}

// set a new next address
void Link::setNext(Link*next) {this->next=next;}

// set a new previous address
void Link::setPrev(Link*prev) {this->prev=prev;}

// return the next address
Link*Link::getNext() {return this ->next;}

// return the previous address
Link*Link::getPrev() {return this ->prev;}


// constructor
TextClass:: TextClass()
{
    // head and tail are set to nullptr
    head = nullptr;
    tail = nullptr;
}

// destructor
TextClass::~TextClass()
{
    // call removeHead until head = nullptr;
    while(head!=nullptr)
    {
        removeHead();
    }
}


// add value at tail
voidTextClass::addTail(charletter)
{
    // if head == nullptr
    if(tail==nullptr)
    {
        // head and tail = new link
        head=tail=newLink(letter);
    }
        // else
    else
    {
        // create new link and insert it at tail
        Link*temp = new Link (letter, nullptr, tail);
        tail->setNext(temp);
        // change tail
        tail = temp;
    }
}


// return the contents of list
US>string TextClass::displayList()
{

    // create a variable that stores contents for string and stringstream
    string output;
    std::stringstreams;
    // create a link that walks down the list and it starts from head
    Link* temp=head;
    // while the link!= nullptr
    while(temp!=nullptr)
    {
        // copy the value in the link to stringstream
        ss<<temp->getValue()<
        // move the link forward
        temp=temp->getNext();
    }

    // copy the value in stringstream to string
    output =ss.str();

    // return the string
    return output;
}

// connect two lists
voidTextClass::append (TextClass const&otherList)
{
    // create a link that stores the head of otherList
    Link*temp=otherList.head;

    // connect tworinks
    // tail next should point to head of otherLink
    while(temp!=nullptr)
    {
        addTail(temp->getValue());
        temp=temp->getNext();
    }

}

// remove head
voidTextClass::removeHead()
{
    // save the link at head to delete later
    Link* temp=head;
    // update head
    head=head->getNext();
    // if head is null after update
    if(head==nullptr)
    {
        //tail=nullptr
        tail = nullptr;
    }
        // else update preview of new link
    else
    {
        head->setPrev(nullptr);
    }
    // now delete the old link
    delete temp;
}

TextClass.h

#include<iostream>


using std::string;

classLink {
private:
    char value; // stores chat type value
    Link * next; // stores the address of next link
    Link*prev;//stores the address of previous link

public:
    Link(charletter, Link*next=nullptr, Link*prev=nullptr); // constructor
    ~Link();//destructor
    chargeValue(); // return the value in the link
    void setNext(Link*next); // set a new next address
    void setPrev (Link*prev); // set a new previous address
    Link*getNext(); // return the next address
    Link* getPrev(); // return the previous address
};


classTextClass{
private:
    Link*head;//track the head link of queue
    Link*tail;//track the tail link of queue
public:
    TextClass(); // constructor
    ~TextClass();//destructor

    void addTail (charletter); // add value at tail
    string displayList(); // return the contents of list
    void append (TextClass const&otherList); // connect two lists
    void removeHead(); // remove head
};

c++

2022-09-30 21:59

2 Answers

The presentation TextClass is delete all of its list elements in the destructor.In other words, the TextClass instance itself and its list elements have the same life span.This means that sharing list elements with other TextClass instances will malfunction.

Regarding the topic copy constructor, according to Copy 12.8 Class Object of JIS X 3014:2003 (sorry it's old)

12.8-4 If the class definition does not explicitly declare a copy constructor, the copy constructor is implicitly declared.
12.8-8 Implicitly Defined Copy Constructors Copy Partial Objects by Member

and so on.The member of the presentation example TextClass is simply a pointer, so the pointer value is copied.They make what is commonly called a Shallow copy.As a result, the pointer values are the same at the source and destination, contrary to the previous assumption, "Don't share list elements in different instances."

For append(TextClass), this argument passes a value, which launches the (implicit) copy constructor to copy.In other words, the mainsecond inside and the provisional argument otherList inside append are separate instances copied by an implicit copy constructor, so they share the list elements.

The copied otherList is discarded at the end of the expression containing the function call. C++ is when the destructor is called when you generate a temporary object in the function argument list, so the list element is deleted.

Reference append(TextClass&) does not cause any problems because there is no copy, i.e., there is no discard.

Other solutions include, for example,
- Make a serious deep copy TextClass::TextClass(const TextClass&)
- std::shared_ptrto make members smart pointers
The former may be too much for this purpose = It's just too late to handle it unnecessarily heavy, and the latter may be too early at this point in time of learning.


2022-09-30 21:59

I think the explanation on this page is easy to understand.

[C++] Class Notes with Pointers on Members (Double Release, Copy Constructor, Replacement Operator)


2022-09-30 21:59

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.