2

I am trying to do a deep copy of class B, but A doesn't get set.

Why does b3->print return a garbage number instead of 1?

From what I understand, b2 and b3 are both pointing to the same A object. but I created a new object on the heap with B's copy constructor. so why are they both still poiting to the same object?

I hope this makes sense.

#include <cstdlib>
#include <iostream>

using namespace std;

class A{
      int num;
public:
       A(int n):num(n){ cout<< "A "<< num << " constructor" <<endl;}  
       ~A(){ cout<< "A "<< num <<" destructor. " <<endl; }   

       int print(){
        cout<< num<< endl;
       }
};

class B{
      A *a;
      int num;
public:
       B(int n):num(n){
           a = new A(n);
           cout<< "B "<< num <<" constructor" <<endl;    
       }  
       ~B(){
            delete a; 
            cout<< "B "<< num <<" destructor"<<endl; 
       }    
       // Copy contructor
       B(const B & b): a(new A(b.num)){ 
       } 

       <strike>int<\strike> void print(){
        cout<< num << endl;
       }

       int get_num(){
           return num;
       }
};

int main(int argc, char *argv[])
{ 
    B *b2 = new B(1);
    B *b3(b2);
    b2->print();
    delete b2;
    b3->print();
    system("PAUSE");
    return EXIT_SUCCESS;
}
nandeesh
  • 24,740
  • 6
  • 69
  • 79
124697
  • 22,097
  • 68
  • 188
  • 315

5 Answers5

15

B *b3(b2); doesn't do what you think.

It's equivalent to B* b3 = b2. The pointers will point to the same location. When you do delete b2;, you're also freeing the memory pointed to by b3.

To do a deep copy, do:

 B* b3 = new B(*b2);

There's also undefined behaviour here:

int print(){
   cout<< num << endl;
}

because you never return. Change the return type to void.

To get the value expected:

B(const B & b): a(new A(b.num)), num(b.num){ 
} 
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 1
    To make it clearer to OP, you didn't copy `num` in B's copy constructor, what you did is copy `num` to `a.num` – Haozhun Aug 02 '12 at 17:29
1

Other answers to this question will explain about how pointers work, but you should also understand that not using pointers is a better solution. C++'s default behaviors work well with value semantics. If you hold objects by value then the default copy ctor and assignment operators will do a 'deep copy'.

class B{
    A a;
    int num;
public:
    B(int n): a(n), num(n){
        cout<< "B "<< num <<" constructor" <<endl;    
    }    

    void print(){
        cout<< num << endl;
    }

    int get_num(){
        return num;
    }
};

Also, if you do use owning pointers you should usually use smart pointers.

bames53
  • 86,085
  • 15
  • 179
  • 244
0

I think you probably intended to write something like this:

#include <iostream>

class A
{
public:
    A(int n) : num_(n) {}

    void print() { std::cout << num() << std::endl; }

    int num() const { return num_; }

private:
    int num_;
};

class B
{
public:
    B(int n) : a(n) {}

    int num() const { return a.num(); }

private:
    A a;
};

int main()
{
    B b(1);
    B b2 = b; // deep copy
}

As you can see:

  1. B doesn't have its own num_ member. Duplication should be avoided.
  2. There's no need to implement the copy constructor or assignment operator (rule-of-three).
  3. Not need to use new here.
StackedCrooked
  • 34,653
  • 44
  • 154
  • 278
0

here you are not copying b2

B *b3(b2);

instead you are making b3 point to b2

you should have

B *b3 = new B(*b2);
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
AndersK
  • 35,813
  • 6
  • 60
  • 86
-7

There is no such things as shallow/deep copy in c++. You either have values or pointers/references that get copied, and that fully defines the semantics of the copy operation.

yuri kilochek
  • 12,709
  • 2
  • 32
  • 59
  • 2
    Wrong! Deep/shallow copies do exist. You can copy pointers, and you can deep-copy pointers. – Luchian Grigore Aug 02 '12 at 17:32
  • @LuchianGrigore `T* p2 = new T(*p1);` is not copying a pointer, its copying an object through a pointer, and getting a pointer to the copy. – yuri kilochek Aug 02 '12 at 17:34
  • That's not what I'm arguing. I'm arguing your first statement - `There is no such things as shallow/deep copy in c++.` which is completely false and missleading. – Luchian Grigore Aug 02 '12 at 17:35
  • @LuchianGrigore then how does a deep copy look if not like I showed? – yuri kilochek Aug 02 '12 at 17:37
  • 2
    To perform a deep copy, you define your own copy-ctor and assignment operator to copy managed objects, not just pointers. You can easily google this. I didn't say that's not how you do a deep copy, I just said your first statement from the answer is wrong. – Luchian Grigore Aug 02 '12 at 17:38
  • @yurikilochek, `T* p2 = new T(*p1);` _is_ deep copy. That's what the terminology is in C++. Maybe it means differently in your language, or in some other context you know, but it _is_ deep copy in C++. – Shahbaz Aug 02 '12 at 21:09