8

Good morning. I am having trouble understanding the logic behind deep and shallow copying with objects in C++ in a shared project, so I have created the following example.

int main() {
    ObjectAType* objecta = ObjectAType::New();
    ObjectBType* objectb = ObjectBType::New();

    // some operation to populate data members of object a
    objecta->Operation();

    // assume I have accessors to return datamembers of object a
    // I wish to make a deep copy of SOME of those data members into object b
    objectb->AlignWithA(objecta);

    objecta->Delete();
    objectb->Delete();

    return 0;
}

Now given the object b class function as follows:

public:
void ObjectBType::AlignWithA(ObjectAType* objecta) {
    this->ObjectBDataMember = objecta->DataAccessor();
}
protected:
int ObjectBDataMember;

And the data accessor is just something like this within the class def,

public:
int ObjectAType::DataAccessor() {
    return this->ObjectADataMember;
}
protected:
int ObjectADataMember;

I have a few resulting questions.

1) Since in object b, the data member is declared as

int ObjectBDataMember; 

and not as

int *ObjectBDataMember;

why is the data member accessed as

this->ObjectBDataMember

and not as

this.ObjectBDataMember

?

2) Is this a deep or shallow copy?

I apologize if I have left out important bits. I'm not much of a programmer so things like this easily confuse me. The literature has just confused me further. Thank you for your time.

Andy K.
  • 355
  • 1
  • 4
  • 14
  • I should note that when I play with this type of example, I can delete object a after the assignment and the value in object b remains. I don't know if it just happens to still be sitting on the stack or what, but in a simple case there is no seg fault or anything. – Andy K. Jan 16 '13 at 18:11
  • Thank you all. You guys cleared everything up for me. It is much appreciated. – Andy K. Jan 16 '13 at 19:03

5 Answers5

7
  1. In C++, this is defined as being a (non-modifiable) pointer to the current object. For that reason, you use this->aMember to access aMember. This is independent of the type that aMember has. (Note: Using this->aMember is equivalent to just using aMember as long as there are no local variables or function parameters using that same name).

  2. Because ObjectBDataMember is an int, copying it is not referred to as either shallow or deep. Those concepts are only used in the context of copying pointers.

For example:

ObjectBType* b1 = new ObjectBType();

ObjectBType* b2 = b1; // shallow copy. b1 and b2 refer to the same object.
ObjectBType* b3 = new ObjectBType(*b1); /* deep copy. b1 and b3 refer to 
  different objects that happen to have the same value. */
Bart van Ingen Schenau
  • 15,488
  • 4
  • 32
  • 41
  • +1 Great answer!! But could you pretty please format the code so it fits in one page-width? (if only I had a +2 to offer as incentive) –  Jan 16 '13 at 18:19
4

"Why is the data member accessed as this->ObjectBDataMember and not as this.ObjectBDataMember?"

That's because this is a pointer, and the -> operator follows the pointer that comes before it to access the member that comes after it.

"Is this a deep or shallow copy?"

If you mean the copy of the integer variable, you can call that a shallow copy, but there's no need to qualify it as such because int is not a data structure.

The term "deep copy" refers to a recursive copying of all objects associated to the object being copied: if a data structure S contains member variables which are pointers, deep copying an instance of S (say, s1) into another instance of S (say, s2) means recursively copying each object pointed by variables of s1 so that s2 will be associated to copies of those objects, rather than to the same objects to which s1 is associated (that would be the case for shallow copying).

Here, you do not have any pointer member variables, so the concept of "deep" vs "shallow" copy loses its meaning in this context.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Thank you very much. As a follow up to make sure I understand then, ObjectADataMember and ObjectBDataMemver both refer to the same memory location, so if I change one I change the other--is that correct? Is there a simple way (following this general structure) to make ObjectBDataMember get a COPY of ObjectADataMember so that I can delete ObjectA while ObjectB still retains the variable? My colleague might have a non-standard destructor--I'm not sure. – Andy K. Jan 16 '13 at 18:53
  • 1
    @AndyK.: no, `ObjectADataMember` and `ObjectBDataMember` are two integer variables, they have two distinct values (they are not pointers nor references). deleting one object will not affect the other – Andy Prowl Jan 16 '13 at 18:58
  • Brilliant, that answers everything. Thank you very much. I'm not a computer scientist--I'm used to procedural programming to perform specific tasks. I got roped into integrating my algorithms into my colleague's API and this is a whole new world. – Andy K. Jan 16 '13 at 19:02
1
  1. You use -> when you have a pointer, and . when you have a reference. The data member is accessed as this->ObjectBDataMember because this is a non-modifiable pointer to self. Therefore you need the -> (offset) operator to access its ObjectBDataMember. It should be noted that you don't have to use the self-reference this pointer to access an object's own data members. It is just a style used to emphasis that the code is accessing the object's own data member. Useful when you are accessing another object's data members and they have the same members (due to being the same object type).

  2. These objects have no allocated objects, merely plain old data types. So it is a shallow copy. A shallow copy of an object copies its values but doesn't allocate any new objects. It only copies the pointers to any allocated objects. A deep copy makes a copy of all value type members, as well as creating its own allocated objects (usually copying over the values in the source copied objects sub objects).

StarPilot
  • 2,246
  • 1
  • 16
  • 18
0

this->ObjectBDataMember has nothing to do with deep or shallow copy. this is a pointer so it's members are always accessed through ->. Well, you could do (*this).ObjectBDataMember.

The difference between

int ObjectBDataMember;

and

int *ObjectBDataMember;

is if you want to set it's value you'd do:

this->ObjectBDataMember = 5;

vs

*(this->ObjectBDataMember) = 5;
0
  1. because this is ObjectBType* (pointer), so to access its members you need to specify ->. BTW, this is implicit variable in member functions and you can omit it: ObjectBDataMember = objecta->DataAccessor();
  2. The type of ObjectADataMember is int, it's fundamental type (not compound), so it's just a copy. Temp "deep copy" is applicable to compound types.

I'd recommend first to finish any good C++ book, this will resolve tons of potential questions like this one

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112