Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Class Copy (pointer copy)

It is my understanding that when you make a copy of a class that defines a pointer variable, the pointer is copied, but the data that the pointer is pointing to is not.

My question is: Is one to assume that the "pointer copy" in this case is simply instantiating a new pointer (dynamic memory allocation) of the same type? Eg., the new pointer is simply a new allocation containing an arbitrary memory address and one should take care to point that new pointer to the appropriate memory address?

I presume there is a quite simple answer to this question, and I apologize for its trivial nature, but I am trying to understand pointers at a deeper level and this came up upon my researching pointers on the internet.

Regards,

Chad

like image 591
Chad Kemp Avatar asked Feb 17 '11 18:02

Chad Kemp


4 Answers

The pointer will be simply copied as a value - so both classes will point to the same original memory, no new allocation takes place. Shallow copy - this is what the language does by default.

If you need to allocate new memory and make a copy of the data you have to do that yourself in the copy constructor. Deep copy - you have to do this yourself

edit: This is one of the advantages of C++, you are free to decide how copying works. It might be that a copy of the object which only does read access to the memory can avoid the cost of copying the memory. You can also implement classes which only make a copy of the original data if the new object needs to do a write.

like image 114
Martin Beckett Avatar answered Oct 02 '22 09:10

Martin Beckett


First off, the pointer in your class is static, (i.e. the compiler knows that there is a pointer in this class and what size it is, so no dynamic memory allocation is needed when the class is instantiated).

If you copy the class (and have not special copy constructor defined) then the pointer in the new class will point to the same place in memory as the pointer in the old class. To clarify:

#include <iostream>

class A {
   public:
       int *p;
};

int main() {
    A a,b;
    a.p = new int(10);
    b = a;

    std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
    std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10

    *(b.p) = 3;

    std::cout << "*(a.p) = " << *(a.p) << std::endl; // 3
    std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3

    return 0;
}

Now if you want to allocate new memory when copying, you need to write a copy constructor and a copy assignment constructor:

#include <iostream>

class A {
   public:
       int *p;

       A() : p(0) {}
       A(const A& other) { // copy constructor
           p = new int(*other.p);
       }

       A& operator=(const A& other) { // copy assignment constructor
           // protect against self assignment
           if (this != &other) {
               if (p != 0) {
                   *p = *other.p;
               } else { // p is null - no memory allocated yet
                   p = new int(*other.p);
               }
           }
           return *this;
       }

       ~A() { // destructor
           delete p;
       }
};


int main() {
    A a,b;
    a.p = new int(10);
    b = a;

    std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
    std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10

    *(b.p) = 3;

    std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
    std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3

    return 0;
}

When you do this you should also write a destructor (see Rule of three ), because the memory that is being allocated in the copy / copy assignment constructors needs to be de-allocated if the class is destroyed:

like image 26
Paul Avatar answered Oct 02 '22 11:10

Paul


Pointers don't instantiate dynamic memory allocation. Pointers and allocations are entirely different things.

If you copy a pointer that points to dynamically allocated memory, you have two pointers pointing at the same allocated memory. Since you've copied it, it already points to the memory block. Specifically, if using the compiler-generated copy constructor, the new pointer will point to the exact same thing as the old pointer. You don't need to do anything with it if that's OK.

You do have the problem of when to free the memory. Freeing it twice will typically cause heap corruption, which is nasty. Not freeing it will cause a memory leak, which may be acceptable in some circumstances. Freeing it before the other pointer is through with it will also cause problems. For this reason, people who have multiple pointers to the same memory often go to the Boost project and use their shared_ptr template (which will be in the upcoming new Standard, and is present in most up-to-date systems).

If you want each pointer to point to separate chunks of memory, you have to set that up by writing your own copy constructor, and allocating a new chunk and copying necessary data in it. (You also need to write your own assignment operator, for the exact same reasons, and your own destructor so you can free the memory. There's a rule of thumb, called the Rule of Three, that says if you need to write your own copy constructor, assignment operator, or destructor, you probably need to write all of them.)

like image 45
David Thornley Avatar answered Oct 02 '22 10:10

David Thornley


The copied pointer will point to the exact same address. There's no new allocation.

like image 39
Erik Avatar answered Oct 02 '22 10:10

Erik