C++ deep copying with objects - c++

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.

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).
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. */

"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.

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).
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).

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;

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();
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

Related

C++ Sharing member variables to member instances of classes during initialization

Currently using C++20.
I'm trying to share data from an instance of class A to its member instances of B and C during initialization. Rather than using getter/setters, singletons, dependency injections, etc, I was thinking of just sharing the data by passing them as arguments in the constructors of the member class variables, where each member instance would hold their share of data via some mean (e.g. reference, raw pointer, shared pointer, void pointer, etc).
Classes B and C are intended to always be initialized as members of class A. Ultimately, A should be the last 'owner' of the data such that when A gets deallocated during destruction, the shared data should be deallocated with it. With that in mind, which of these approaches would be acceptable; not violating any major rules and ensuring encapsulation?
A stores and passes the data as shared pointers. B & C stores the arguments as shared pointers.
A stores the data as normal variables, and passes them as void pointers. B & C stores the arguments as void pointers.
A stores the data as normal variables, and passes them as references. B & C stores the arguments as references.
A stores the data as normal variables, and passes them as raw pointers. B & C stores the arguments as raw pointers.
Pseudocode:
class B
{
private:
// Some variable that holds the shared data
};
class C
{
private:
// Some variable that holds the shared data
};
class A
{
private:
// Data to be shared to
B b;
C c;
// Data to be shared
SomeDataType first;
SomeDataType second;
public:
A()
: b{first, second}, c{first}
{
}
};
A stores and passes the data as shared pointers. B & C stores the arguments as shared pointers.
No. A owns the data, no ownership is shared. ("[...], A should be the last 'owner' of the data such that when `A? gets deallocated during destruction, the shared data should be deallocated with it.", if it is the last and first then it can be the only one, no need to share.)
A stores the data as normal variables, and passes them as void pointers. B & C stores the arguments as void pointers.
No. void* is not a solution to a problem you do not have. When in the past one had to use void* there are better alternatives now. Though as there is no need here in the first place this is beyond the scope of this answer.
A stores the data as normal variables, and passes them as references. B & C stores the arguments as references.
No, maybe yes. Reference members have implications. The compiler cannot generate copying for you.
A stores the data as normal variables, and passes them as raw pointers. B & C stores the arguments as raw pointers.
That sounds reasonable. It is raw owning pointers that should be avoided. A raw non-owning pointer that never gets invalid (because the owner is destroyed after observers) is fine. The only phases during which you need to be careful not a not yet valid or not anymore valid pointer is during construction and destruction. It is worth mentioning that during construction of A it is ok to take pointers to members, but only after the member has been initialized you may safely dereference the pointer.

C++ pointer vs object

Could you please clear up a question for me regarding pointer vs object in C++. I have the below code that has a class called "person" and a list that allows for 100 objects of that class type.
class person {...}
int main {
person* mylist;
mylist = new person[100];
mylist[0].set_name("John")
// ...
}
In this code I can call a method of the class by mylist[0].set_name() meaning (by my understanding) that mylist[0] is an object (hence the . operator to call a method). The code works fine.
I have another project where the "person" class is used as a base class to derive classes "carpenter" and "welder". The derived classes simply overwrite a virtual function called salary in the base "person" class to allow for a different calculation of salary.
person* mylist[100];
mylist[0] = new carpenter;
mylist[0]->set_name("John");
This code works fine as well. My question is - why in the first code I can call the set_name method using the . (meaning mylist[0] is an object) and in the second code I have to use the -> operator (meaning mylist[0] is a pointer to the object)?
T* represents a pointer type, which represents a variable that contains a "reference" (usually a memory address) to some instance of type T. Using a real world comparison, a T* pointer stands to T like a street address stands to a building.
Pointers allow you to refer to some instance owned by some other variable, and you can use a valid, non null instance of T* to read and write on a T. In this, they are similar to another C++ concept, references (written as T&), which allow you to alias variables, but differ significantly from pointers by not being objects in their own regard.
A pointer is, in fact, an object itself, with each pointer variable having its own unique address and being thus storable and referenceable. For instance, you can have pointers to pointers (T**) and references to pointers (T*&), but not pointers to references - pointers exist, while references may not (they are usually implemented as pointers underneath though).
To reflect the this "indirect" nature of pointers, C and C++ provide you with two different operators which allow you to dereference a pointer (* and ->), and to reference a variable (&).
For instance, you may do the following:
struct A { int x; };
// ...
A a {};
A *aptr { &a }; // `&` takes the address of `a` and stores it into the `aptr` variable of type `A*`
aptr->x = 33; // `->` is equivalent here to `(*aptr).x`, a.x is now 33
A a2 {};
A **aptrptr { &aptr }; // pointer to pointer
*aptrptr = &a2; // `aptr` now points to `a2`
operator-> is basically syntactic sugar that avoids you some cumbersome expressions like (*aptr).x.
References, being basically just aliases to something else, do not need any special syntax at all, and are always converted transparently when neeeded:
int x { 33 };
int &xref { x }; // `xref` refers to `x`
xref = 12; // `x` is now 33
int y = xref; // copies `x` into `y`, no special syntax needed
Pointers are also used in the C language to access arrays, which always decay to a pointer as soon as they are referred to in expressions. This is messy and it's one of the reasons std::vector and std::array should always be used in their place when feasible.
int x[33];
x[3] = 44; // equivalent to `*(&x[0] + 3) = 44`
Finally, the "indirect" nature of pointers and references allow C++ to convert a Derived* to a Base*, given that a derived class contains a full instance of its base (it gets more complicated with multiple inheritance though).
Every class that inherits or contains from another class containing virtual methods will include a hidden pointer to a _Virtual Method Table`, a list of pointers to functions which will be used to dispatch the virtual methods to the correct implementation.
PS: in modern C++, you should rarely need raw pointers. The correct approach is to use containers such as std::vector, std::array and std::string, and special pointer-like wrappers called smart pointers (like std::unique_ptr) every time you need a pointer for some reason. These will handle the lifetime of a pointer for you, avoiding memory leaks and vastly simplifying memory handling. For the same reason, the new operator should be mostly considered as being deprecated and should not be used at all (unless in placement new expressions, are potentially dangerous if used improperly).
basically the first case works like this: you have an array of objects. To access the object fields and methods you use . operator.
In the second case you have an array of pointers to an object. Pointer is just a memory address, that points to an object of some type. In your case, this is an array of pointers to class person. By default, these pointers are invalid; you have to set them to the address of some existing object. new creates an object on the heap, and returns you an address of that object. In order to access the value behind the pointer, you have to de-reference it. The syntax is this:
some_type obj;
some_type* ptr = &obj; // get the address of the object
(*ptr).some_method(); // de-reference the pointer and call it
ptr->some_method(); // same

How to know the value of a reference

I recently started learning C++ and I can't understand the following code (it's a copy constructor, deep copy):
Car::Car(const Car &c){
this->_make = new string(*(c._make));
this->_model = new string(*(c._model));
this->_year = new int(*(c._year));
}
Here, we are passing by reference so why are we adding the "*" here: *(c._make), shouldn't it just be c._make, as passing by reference already gives the value, what does the * do in this case?
You need * in this->_make = new string(*(c._make)); because make was defined as a pointer:
class Car
{
string* make;
//...
};
This design is pointless - it would be better to hold string by value:
class Car
{
string make;
//...
};
In which case the code in question would look like:
Car::Car(const Car &c){
this->_make = c._make;
//...
}
with no * anywhere.
The * is not being applied to the passed Car object itself, but to its 3 pointer members, _make, _model, and _year. The pointers are being dereferenced when the members are being passed to their respective copy constructors.
It's hard to see why a deep copy is necessary for 3 simple variables. Nevertheless if they were defined as pointers in the class then they need to be dereferenced otherwise you would be copying the address of the values instead of the values themselves. The fact that the object is being passed by reference doesn't mean that its member variables are being referenced as well.
Deep copying is useful when the class includes dynamically allocated arrays, or other classes, etc. But for simpler classes with simple variables (no pointers), a shallow copy should be enough.

Is it right to use the words Deep/Shallow copy of a pointer [duplicate]

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
What is the difference between a deep copy and a shallow copy?
Breadth vs Depth; think in terms of a tree of references with your object as the root node.
Shallow:
The variables A and B refer to different areas of memory, when B is assigned to A the two variables refer to the same area of memory. Later modifications to the contents of either are instantly reflected in the contents of other, as they share contents.
Deep:
The variables A and B refer to different areas of memory, when B is assigned to A the values in the memory area which A points to are copied into the memory area to which B points. Later modifications to the contents of either remain unique to A or B; the contents are not shared.
Shallow copies duplicate as little as possible. A shallow copy of a collection is a copy of the collection structure, not the elements. With a shallow copy, two collections now share the individual elements.
Deep copies duplicate everything. A deep copy of a collection is two collections with all of the elements in the original collection duplicated.
Try to consider following image
For example Object.MemberwiseClone creates a shallow copy link
and using ICloneable interface you can get deep copy as described here
In short, it depends on what points to what. In a shallow copy, object B points to object A's location in memory. In deep copy, all things in object A's memory location get copied to object B's memory location.
This wiki article has a great diagram.
http://en.wikipedia.org/wiki/Object_copy
Especially For iOS Developers:
If B is a shallow copy of A, then for primitive data it's like B = [A assign]; and for objects it's like B = [A retain];
B and A point to the same memory location
If B is a deep copy of A, then it is like B = [A copy];
B and A point to different memory locations
B memory address is same as A's
B has same contents as A's
Shallow copy: Copies the member values from one object into another.
Deep Copy: Copies the member values from one object into another.
Any pointer objects are duplicated and Deep Copied.
Example:
class String
{
int size;
char* data;
};
String s1("Ace"); // s1.size = 3 s1.data=0x0000F000
String s2 = shallowCopy(s1);
// s2.size =3 s2.data = 0X0000F000
String s3 = deepCopy(s1);
// s3.size =3 s3.data = 0x0000F00F
// (With Ace copied to this location.)
Just for the sake of easy understanding you could follow this article:
https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
Shallow Copy:
Deep Copy:
I haven't seen a short, easy to understand answer here--so I'll give it a try.
With a shallow copy, any object pointed to by the source is also pointed to by the destination (so that no referenced objects are copied).
With a deep copy, any object pointed to by the source is copied and the copy is pointed to by the destination (so there will now be 2 of each referenced object). This recurses down the object tree.
char * Source = "Hello, world.";
char * ShallowCopy = Source;
char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);
'ShallowCopy' points to the same location in memory as 'Source' does.
'DeepCopy' points to a different location in memory, but the contents are the same.
{Imagine two objects: A and B of same type _t(with respect to C++) and you are thinking about shallow/deep copying A to B}
Shallow Copy:
Simply makes a copy of the reference to A into B. Think about it as a copy of A's Address.
So, the addresses of A and B will be the same i.e. they will be pointing to the same memory location i.e. data contents.
Deep copy:
Simply makes a copy of all the members of A, allocates memory in a different location for B and then assigns the copied members to B to achieve deep copy. In this way, if A becomes non-existant B is still valid in the memory. The correct term to use would be cloning, where you know that they both are totally the same, but yet different (i.e. stored as two different entities in the memory space). You can also provide your clone wrapper where you can decide via inclusion/exclusion list which properties to select during deep copy. This is quite a common practice when you create APIs.
You can choose to do a Shallow Copy ONLY_IF you understand the stakes involved. When you have enormous number of pointers to deal with in C++ or C, doing a shallow copy of an object is REALLY a bad idea.
EXAMPLE_OF_DEEP COPY_ An example is, when you are trying to do image processing and object recognition you need to mask "Irrelevant and Repetitive Motion" out of your processing areas. If you are using image pointers, then you might have the specification to save those mask images. NOW... if you do a shallow copy of the image, when the pointer references are KILLED from the stack, you lost the reference and its copy i.e. there will be a runtime error of access violation at some point. In this case, what you need is a deep copy of your image by CLONING it. In this way you can retrieve the masks in case you need them in the future.
EXAMPLE_OF_SHALLOW_COPY I am not extremely knowledgeable compared to the users in StackOverflow so feel free to delete this part and put a good example if you can clarify. But I really think it is not a good idea to do shallow copy if you know that your program is gonna run for an infinite period of time i.e. continuous "push-pop" operation over the stack with function calls. If you are demonstrating something to an amateur or novice person (e.g. C/C++ tutorial stuff) then it is probably okay. But if you are running an application such as surveillance and detection system, or Sonar Tracking System, you are not supposed to keep shallow copying your objects around because it will kill your program sooner or later.
What is Shallow Copy?
Shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, only the reference addresses are copied i.e., only the memory address is copied.
In this figure, the MainObject1 has fields field1 of type int, and ContainObject1 of type ContainObject. When you do a shallow copy of MainObject1, MainObject2 is created with field2 containing the copied value of field1 and still pointing to ContainObject1 itself. Note that since field1 is of primitive type, its value is copied to field2 but since ContainedObject1 is an object, MainObject2 still points to ContainObject1. So any changes made to ContainObject1 in MainObject1 will be reflected in MainObject2.
Now if this is shallow copy, lets see what's deep copy?
What is Deep Copy?
A deep copy copies all fields, and makes copies of dynamically allocated memory pointed to by the fields. A deep copy occurs when an object is copied along with the objects to which it refers.
In this figure, the MainObject1 have fields field1 of type int, and ContainObject1 of type ContainObject. When you do a deep copy of MainObject1, MainObject2 is created with field2 containing the copied value of field1 and ContainObject2 containing the copied value of ContainObject1. Note any changes made to ContainObject1 in MainObject1 will not reflect in MainObject2.
good article
Deep Copy
A deep copy copies all fields, and makes copies of dynamically allocated memory pointed to by the fields. A deep copy occurs when an object is copied along with the objects to which it refers.
Shallow Copy
Shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the reference addresses are copied i.e., only the memory address is copied.
In object oriented programming, a type includes a collection of member fields. These fields may be stored either by value or by reference (i.e., a pointer to a value).
In a shallow copy, a new instance of the type is created and the values are copied into the new instance. The reference pointers are also copied just like the values. Therefore, the references are pointing to the original objects. Any changes to the members that are stored by reference appear in both the original and the copy, since no copy was made of the referenced object.
In a deep copy, the fields that are stored by value are copied as before, but the pointers to objects stored by reference are not copied. Instead, a deep copy is made of the referenced object, and a pointer to the new object is stored. Any changes that are made to those referenced objects will not affect other copies of the object.
I would like to give example rather than the formal definition.
var originalObject = {
a : 1,
b : 2,
c : 3,
};
This code shows a shallow copy:
var copyObject1 = originalObject;
console.log(copyObject1.a); // it will print 1
console.log(originalObject.a); // it will also print 1
copyObject1.a = 4;
console.log(copyObject1.a); //now it will print 4
console.log(originalObject.a); // now it will also print 4
var copyObject2 = Object.assign({}, originalObject);
console.log(copyObject2.a); // it will print 1
console.log(originalObject.a); // it will also print 1
copyObject2.a = 4;
console.log(copyObject2.a); // now it will print 4
console.log(originalObject.a); // now it will print 1
This code shows a deep copy:
var copyObject2 = Object.assign({}, originalObject);
console.log(copyObject2.a); // it will print 1
console.log(originalObject.a); // it will also print 1
copyObject2.a = 4;
console.log(copyObject2.a); // now it will print 4
console.log(originalObject.a); // !! now it will print 1 !!
'ShallowCopy' points to the same location in memory as 'Source' does. 'DeepCopy' points to a different location in memory, but the contents are the same.
Shallow Cloning:
Definition: "A shallow copy of an object copies the ‘main’ object, but doesn’t copy the inner objects."
When a custom object (eg. Employee) has just primitive, String type variables then you use Shallow Cloning.
Employee e = new Employee(2, "john cena");
Employee e2=e.clone();
You return super.clone(); in the overridden clone() method and your job is over.
Deep Cloning:
Definition: "Unlike the shallow copy, a deep copy is a fully independent copy of an object."
Means when an Employee object holds another custom object:
Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");
Then you have to write the code to clone the 'Address' object as well in the overridden clone() method. Otherwise the Address object won't clone and it causes a bug when you change value of Address in cloned Employee object, which reflects the original one too.
var source = { firstName="Jane", lastname="Jones" };
var shallow = ShallowCopyOf(source);
var deep = DeepCopyOf(source);
source.lastName = "Smith";
WriteLine(source.lastName); // prints Smith
WriteLine(shallow.lastName); // prints Smith
WriteLine(deep.lastName); // prints Jones
Shallow Copy- Reference variable inside original and shallow-copied objects have reference to common object.
Deep Copy- Reference variable inside original and deep-copied objects have reference to different object.
clone always does shallow copy.
public class Language implements Cloneable{
String name;
public Language(String name){
this.name=name;
}
public String getName() {
return name;
}
#Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
main class is following-
public static void main(String args[]) throws ClassNotFoundException, CloneNotSupportedException{
ArrayList<Language> list=new ArrayList<Language>();
list.add(new Language("C"));
list.add(new Language("JAVA"));
ArrayList<Language> shallow=(ArrayList<Language>) list.clone();
//We used here clone since this always shallow copied.
System.out.println(list==shallow);
for(int i=0;i<list.size();i++)
System.out.println(list.get(i)==shallow.get(i));//true
ArrayList<Language> deep=new ArrayList<Language>();
for(Language language:list){
deep.add((Language) language.clone());
}
System.out.println(list==deep);
for(int i=0;i<list.size();i++)
System.out.println(list.get(i)==deep.get(i));//false
}
OutPut of above will be-
false true true
false false false
Any change made in origional object will reflect in shallow object not in deep object.
list.get(0).name="ViSuaLBaSiC";
System.out.println(shallow.get(0).getName()+" "+deep.get(0).getName());
OutPut- ViSuaLBaSiC C
Imagine there are two arrays called arr1 and arr2.
arr1 = arr2; //shallow copy
arr1 = arr2.clone(); //deep copy
In Simple Terms, a Shallow Copy is similar to Call By Reference and a Deep Copy is similar to Call By Value
In Call By Reference, Both formal and actual parameters of a function refers to same memory location and the value.
In Call By Value, Both formal and actual parameters of a functions refers to different memory location but having the same value.
A shallow copy constructs a new compound object and insert its references into it to the original object.
Unlike shallow copy, deepcopy constructs new compound object and also inserts copies of the original objects of original compound object.
Lets take an example.
import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)
Above code prints FALSE.
Let see how.
Original compound object x=[1,[2]] (called as compound because it has object inside object (Inception))
as you can see in the image, there is a list inside list.
Then we create a shallow copy of it using y = copy.copy(x). What python does here is, it will create a new compound object but objects inside them are pointing to the orignal objects.
In the image it has created a new copy for outer list. but the inner list remains same as the original one.
Now we create deepcopy of it using z = copy.deepcopy(x). what python does here is, it will create new object for outer list as well as inner list. as shown in the image below (red highlighted).
At the end code prints False, as y and z are not same objects.
HTH.
struct sample
{
char * ptr;
}
void shallowcpy(sample & dest, sample & src)
{
dest.ptr=src.ptr;
}
void deepcpy(sample & dest, sample & src)
{
dest.ptr=malloc(strlen(src.ptr)+1);
memcpy(dest.ptr,src.ptr);
}
To add more to other answers,
a Shallow Copy of an object performs copy by value for value types
based properties, and copy by reference for reference types based properties.
a Deep Copy of an object performs copy by value for value types based
properties, as well as copy by value for reference types based
properties deep in the hierarchy (of reference types)
Shallow copy will not create new reference but deep copy will create the new reference.
Here is the program to explain the deep and shallow copy.
public class DeepAndShollowCopy {
int id;
String name;
List<String> testlist = new ArrayList<>();
/*
// To performing Shallow Copy
// Note: Here we are not creating any references.
public DeepAndShollowCopy(int id, String name, List<String>testlist)
{
System.out.println("Shallow Copy for Object initialization");
this.id = id;
this.name = name;
this.testlist = testlist;
}
*/
// To performing Deep Copy
// Note: Here we are creating one references( Al arraylist object ).
public DeepAndShollowCopy(int id, String name, List<String> testlist) {
System.out.println("Deep Copy for Object initialization");
this.id = id;
this.name = name;
String item;
List<String> Al = new ArrayList<>();
Iterator<String> itr = testlist.iterator();
while (itr.hasNext()) {
item = itr.next();
Al.add(item);
}
this.testlist = Al;
}
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Oracle");
list.add("C++");
DeepAndShollowCopy copy=new DeepAndShollowCopy(10,"Testing", list);
System.out.println(copy.toString());
}
#Override
public String toString() {
return "DeepAndShollowCopy [id=" + id + ", name=" + name + ", testlist=" + testlist + "]";
}
}
Taken from [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Deep copy involves using the contents of one object to create another instance of the same class. In a deep copy, the two objects may contain ht same information but the target object will have its own buffers and resources. the destruction of either object will not affect the remaining object. The overloaded assignment operator would create a deep copy of objects.
Shallow copy involves copying the contents of one object into another instance of the same class thus creating a mirror image. Owing to straight copying of references and pointers, the two objects will share the same externally contained contents of the other object to be unpredictable.
Explanation:
Using a copy constructor we simply copy the data values member by member. This method of copying is called shallow copy. If the object is a simple class, comprised of built in types and no pointers this would be acceptable. This function would use the values and the objects and its behavior would not be altered with a shallow copy, only the addresses of pointers that are members are copied and not the value the address is pointing to. The data values of the object would then be inadvertently altered by the function. When the function goes out of scope, the copy of the object with all its data is popped off the stack.
If the object has any pointers a deep copy needs to be executed. With the deep copy of an object, memory is allocated for the object in free store and the elements pointed to are copied. A deep copy is used for objects that are returned from a function.
I came to understand from the following lines.
Shallow copy copies an object value type(int, float, bool) fields in to target object and object's reference types(string, class etc) are copied as references in target object. In this target reference types will be pointing to the memory location of source object.
Deep copy copies an object's value and reference types into a complete new copy of the target objects. This means both the value types and reference types will be allocated a new memory locations.
Shallow copying is creating a new object and then copying the non-static fields of the current object to the new object. If a field is a value type --> a bit-by-bit copy of the field is performed; for a reference type --> the reference is copied but the referred object is not; therefore the original object and its clone refer to the same object.
Deep copy is creating a new object and then copying the nonstatic fields of the current object to the new object. If a field is a value type --> a bit-by-bit copy of the field is performed. If a field is a reference type --> a new copy of the referred object is performed. The classes to be cloned must be flagged as [Serializable].
Copying ararys :
Array is a class, which means it is reference type so array1 = array2 results
in two variables that reference the same array.
But look at this example:
static void Main()
{
int[] arr1 = new int[] { 1, 2, 3, 4, 5 };
int[] arr2 = new int[] { 6, 7, 8, 9, 0 };
Console.WriteLine(arr1[2] + " " + arr2[2]);
arr2 = arr1;
Console.WriteLine(arr1[2] + " " + arr2[2]);
arr2 = (int[])arr1.Clone();
arr1[2] = 12;
Console.WriteLine(arr1[2] + " " + arr2[2]);
}
shallow clone means that only the memory represented by the cloned array is copied.
If the array contains value type objects, the values are copied;
if the array contains reference type, only the references are copied - so as a result there are two arrays whose members reference the same objects.
To create a deep copy—where reference type are duplicated, you must loop through the array and clone each element manually.
The copy constructor is used to initialize the new object with the previously created object of the same class. By default compiler wrote a shallow copy. Shallow copy works fine when dynamic memory allocation is not involved because when dynamic memory allocation is involved then both objects will points towards the same memory location in a heap, Therefore to remove this problem we wrote deep copy so both objects have their own copy of attributes in a memory.
In order to read the details with complete examples and explanations you could see the article C++ constructors.
To add just a little more for confusion between shallow copy and simply assign a new variable name to list.
"Say we have:
x = [
[1,2,3],
[4,5,6],
]
This statement creates 3 lists: 2 inner lists and one outer list. A reference to the outer list is then made available under the name x. If we do
y = x
no data gets copied. We still have the same 3 lists in memory somewhere. All this did is make the outer list available under the name y, in addition to its previous name x. If we do
y = list(x)
or
y = x[:]
This creates a new list with the same contents as x. List x contained a reference to the 2 inner lists, so the new list will also contain a reference to those same 2 inner lists. Only one list is copied—the outer list.
Now there are 4 lists in memory, the two inner lists, the outer list, and the copy of the outer list. The original outer list is available under the name x, and the new outer list is made available under the name y.
The inner lists have not been copied! You can access and edit the inner lists from either x or y at this point!
If you have a two dimensional (or higher) list, or any kind of nested data structure, and you want to make a full copy of everything, then you want to use the deepcopy() function in the copy module. Your solution also works for 2-D lists, as iterates over the items in the outer list and makes a copy of each of them, then builds a new outer list for all the inner copies."
source: https://www.reddit.com/r/learnpython/comments/1afldr/why_is_copying_a_list_so_damn_difficult_in_python/

How are pointers to data members allocated/stored in memory?

This is one topic that is not making sense to me. Pointers to data members of a class can be declared and used. However,
What is the logic that supports the idea ? [I am not talking about the syntax, but the logic of this feature]
Also,if i understand this correctly, this would imply an indefinite/variable amount of memory being allocated at the pointer initialization as any number of objects may exist at that time. Also, new objects may be created and destroyed during runtime. Hence, in effect, a single statement will cause a large number of allocations/deallocations. This seems rather counter-intuitive as compared to the rest of the language. Or is my understanding of this incorrect ? I dont think there is any other single initialization statement that will implicitly affect program execution as widely as this.
Lastly, how is memory allocated to these pointers ? Where are they placed with respect to objects ? Is it possible to see physical memory addresses of these pointers ?
A single declaration of a pointer to a data member, creates pointers for every object of that class.
No, it does not. A pointer to a member is a special object that is very different from a pointer; it is a lot more similar to an offset. Given a pointer to an object of the class and a member pointer, you'd be able to get the value of a member; without the pointer to an object of a class a pointer to a member is useless.
Questions 2 and 3 stem from the same basic misunderstanding.
A single declaration of a pointer to a data member, creates pointers for every object of that class.
No. It creates a pointer to a member (which can be though of as an offset from the base of object)
You can then use it with a pointer to an object to get that member.
struct S
{
int x;
int y;
};
int S::* ptrToMember = &S::x; // Pointer to a member.
S obj;
int* ptrToData = &obj.x; // Pointer to object
// that happens to be a member
Notice in creating the pointer to a member we don't use an object (we just use the type information). So this pointer is an offset into the class to get a specific member.
You can access the data member via a pointer or object.
(obj.*ptrToMember) = 5; // Assign via pointer to member (requires an object)
*ptrToData = 6; // Assign via pointer already points at object.
Why does this happen as opposed to a single pointer being created to point to only one specific instance of the class ?
That is called a pointer.
A similar but parallel concept (see above).
What is the logic that supports the idea ?
Silly example:
void addOneToMember(S& obj, int S::* member) { (obj.*member) += 1; }
void addOneToX(S& obj) { addOneToMember(obj, &Obj::x);}
void addOneToY(S& obj) { addOneToMember(obj, &Obj::y);}
Also,if i understand this correctly, this would imply an indefinite/variable amount of memory being allocated at the pointer initialization as any number of objects may exist at that time.
No. Because a pointer to a member is just an offset into an object. You still need the actual object to get the value.
Lastly, how is memory allocated to these pointers ?
Same way as other objects. There is nothing special about them in terms of layout.
But the actual layout is implementation defined. So there is no way of answering this question without referring to the compiler. But it is really of no use to you.
Is it possible to see physical memory addresses of these pointers ?
Sure. They are just like other objects.
// Not that this will provide anything meaningful.
std::cout.write(reinterpret_cast<char*>(&ptrToMember), sizeof(ptrToMember));
// 1) take the address of the pointer to member.
// 2) cast to char* as required by write.
// 3) pass the size of the pointer to member
// and you should write the values printed out.
// Note the values may be non printable but I am sure you can work with that
// Also note the meaning is not useful to you as it is compiler dependent.
Internally, for a class that does not have virtual bases, a pointer-to-member-data just has to hold the offset of the data member from the start of an object of that type. With virtual bases it's a bit more complicated, because the location of the virtual base can change, depending on the type of the most-derived object. Regardless, there's a small amount of data involved, and when you dereference the pointer-to-data-member the compiler generates appropriate code to access it.