Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

copy constructor for a class with pointer to a user defined type

I have seen many examples of copy constructor for classes with member variables as pointer to int or char. Can someone advise on the right way of writing a copy constructor for a class A with a member ptrB which is a pointer to user defined class B please.

Is this correct:

class A {
    private:
      B *ptrB;
    public:
      A() { ptrB = new B; }
      A(const A& other);
      ~A();
}

A::A(const A& other)
{
  ptrB = new B;
  *(ptrB) = *(other.ptrB);
}

and If ptrB was defined like this:

shared_ptr<B> ptrB;

then this?

A::A(const A& other)
{
  ptrB(new B);
  *(ptrB) = *(other.ptrB);
}

Thanks.

like image 325
jambodev Avatar asked Apr 02 '26 01:04

jambodev


1 Answers

Since you tagged the post with "deep-copy" I assume you want the copy constructor to do that. The default copy constructor generated using shared_ptr does not deep copy.

I would suggest that there are two general forms for copying a pointer-like member.

Deep(const Deep& other): ptr(new T(*other.ptr)) {}

and

Shallow(const Shallow& other) = default;

Note, a shallow copy like that won't work for a unique_ptr. By design, unique_ptr prevents that.

Here is an example of each, showing the difference. Nb, using the raw version in practice could easily lead to a memory leak. The important point is that after the shallow copy, modifying the copy modifies the original.

#include <memory>
#include <iostream>

template<typename T, typename TPtr>
struct Deep
{
    TPtr ptr;

    Deep() : ptr(new T) {}

    T get() const { return *ptr; }
    void set(T t) { *ptr = t; }

    Deep(const Deep& other): ptr(new T(*other.ptr)) {}
};

template<typename T, typename TPtr>
struct Shallow
{
    TPtr ptr;

    Shallow() : ptr(new T) {}

    T get() const { return *ptr; }
    void set(T t) { *ptr = t; }

    Shallow(const Shallow& other) = default;
};

template<typename T>
using raw_ptr = T*;

template<typename T>
void test(const T& a1)
{
    auto a2 = a1;
    a2.set(a2.get() + 1);
    std::cout << a1.get() << " " << a2.get() << std::endl;  
}

using std::shared_ptr;

int main()
{
    Deep<int, raw_ptr<int> > rawDeep;
    rawDeep.set(1);
    test(rawDeep);

    Deep<int, shared_ptr<int> > sharedDeep;
    sharedDeep.set(1);
    test(sharedDeep);

    Shallow<int, raw_ptr<int> > rawShallow;
    rawShallow.set(1);
    test(rawShallow);

    Shallow<int, shared_ptr<int> > sharedShallow;
    sharedShallow.set(1);
    test(sharedShallow);
}

http://ideone.com/NltfUO

like image 73
tahsmith Avatar answered Apr 08 '26 17:04

tahsmith