Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

classes with pointer members and no overridden copy constructor

When pointers point to something declared in the same class, am I right in thinking that if you copy such an object that there are multiple sets of pointers but they all point to the same object(s)?

Does this mean there are other objects in the other class instances that have been created but that nothing is pointing to?

And as a side question, would I be right in thinking that a shared pointer would point all the classes at ONE set of objects but in a safe way?

like image 236
Dollarslice Avatar asked Dec 06 '11 14:12

Dollarslice


2 Answers

yes - when you don't define a copy constructor the compiler will issue one for you - which will do a shallow copy - just copy the values(i.e the address) of the pointers.

So the two objects(original and 'copy') will have pointer fields pointing at the same object.

like image 152
Ventsyslav Raikov Avatar answered Sep 20 '22 18:09

Ventsyslav Raikov


If you don't deep copy the object i.e. if you don't override the copy c'tor and do a shallow copy, the pointer(s) will point to the same instance of an object. If you then delete one of the shallow - copied objects then the pointers of the other objects will point to garbage. If you dereference them in any way your program will crash.

Same thing can happen with the assignment operator. So when you have pointers overload them both.

An example:

struct Message
{
    Message(const LogType_E & type_in = LOG_ERROR, const unsigned int & domain_in = 0, const int & msgId_in = 0, const char * msg_in = "");
    int myMsgID;            //!< message id
    unsigned int myDomain;  //!< message domain
    LogType_E myType;       //!< message type
    char * myMsg;           //!< actual message 

    ~Message()
    {
        if(myMsg != NULL) delete [] myMsg;
    }

    Message(const Message &);

    const Message& operator=(const Message & rhs);
};

This is a "message" type used to hold a message with other thingies.

Implementation would look like :

Message::Message(const Message & cp_in):myType(cp_in.myType), myDomain(cp_in.myDomain), myMsgID(cp_in.myMsgID), myMsg(NULL)
{
    if(cp_in.myMsg != NULL)
    {
        myMsg = new char[strlen(cp_in.myMsg)+1];
        memcpy (myMsg, cp_in.myMsg, strlen(cp_in.myMsg)+1); 
    }
}

const Message & Message::operator =(const AX::Base::Log::Message &cp_in)
{
    if (this == &cp_in) // protect against invalid self-assignment
        return *this;

    //deallocate old memory
    if(myMsg != NULL) delete [] myMsg;

    if(cp_in.myMsg != NULL)
    {
    //allocate new memory and copy the elements
        myMsg = new char[strlen(cp_in.myMsg)+1];
        memcpy (myMsg, cp_in.myMsg, strlen(cp_in.myMsg)+1); 
    }

    // copy other data members
    myType = cp_in.myType;
    myDomain = cp_in.myDomain;
    myMsgID = cp_in.myMsgID;

    return *this;
}

That said, please use std::string to avoid all these things - that was just a proof of concept example.

like image 31
FailedDev Avatar answered Sep 19 '22 18:09

FailedDev