answersLogoWhite

0


Best Answer

Lazy copying is a hybrid of the standard shallow-copy and deep-copy mechanisms. Objects that are copy constructed or assigned from existing instances will initially be shallow-copied, meaning their dynamic data members will share the same memory. When an object is mutated whilst sharing memory, its data will be deep copied so as not to affect the shared instances.

In other words, deep-copying is postponed until it is actually required (if at all). For large and complex objects, this can offer a significant memory saving and a major performance boost as a shallow copy is significantly faster than a deep copy, and sharing memory obviously consumes less memory.

In order to implement lazy copying, it is necessary for each instance to be fully aware of all the instances it shares memory with. One of the simplest ways of achieving that is for each instance to maintain bi-directional pointers, similar to those you would find in a doubly-linked list. However, unlike a linked list, there is no need to expose these pointers outside of the class as the class can link and unlink all by itself, via the copy constructor and the assignment operator. All the functionality is encapsulated within the class so the lazy copy mechanism is completely transparent to the end user.

The following implementation provides a brief demonstration of how the mechanism works. It is by no means a complete implementation as it can only handle one type of data, but it serves to demonstrate the key aspects of lazy copying. A more complete implementation would change the data to a template class, thus allowing any type of data to be lazy copied.

The output shows that while each instance of the object occupies separate memory locations, the data they contain is initially shared. We then manipulate the objects to show that deep copying is occurring when it is required, and that destroying a share doesn't affect any remaining shares. If you strip away the trace code in the main function you will see that the lazy copy mechanism is completely transparent; you need never know it exists as it is fully encapsulated within the Object class itself.

// Demonstration of a lazy copy mechanism

// Copyright ©PCForrest, 2012

#include <iostream>

using namespace std;

// Example data container.

class Data

{

friend ostream& operator<<(ostream& os, const Data& data);

public:

inline ~Data(){delete(m_num);}

inline Data():m_num(new int(0)){}

inline Data(const int num):m_num(new int(num)){}

inline Data(const Data& data):m_num(new int(*data.m_num)){}

inline Data& operator=(const Data& data){*m_num=*data.m_num; return(*this);}

inline Data& operator=(const int num){*m_num=num; return(*this);}

inline bool operator==(const Data& data){return(*m_num==*data.m_num);}

inline bool operator!=(const Data& data){return(*m_num!=*data.m_num);}

inline int operator+(const Data& data){return(*m_num+*data.m_num);}

inline int operator+(const int num){return(*m_num+num);}

inline Data& operator+=(const Data& data){*m_num+=*data.m_num; return(*this);}

inline Data& operator+=(const int num){*m_num+=num; return(*this);}

inline int GetNum()const{return(*m_num);}

inline void SetNum(const int num){*m_num=num;}

private:

int * m_num;

};

// Friend function

ostream& operator<<(ostream& os, const Data& data)

{

os<<"Data:0x"<<&data<<" ("<<*data.m_num<<")";

return(os);

}

// Lazy copy class.

class Object

{

friend ostream& operator<<(ostream& os, const Object& object);

public:

inline Object():m_nextshare(NULL),m_prevshare(NULL),m_data(new Data(0)){}

inline Object(const Object& object):m_prevshare(&object.LocateLastShare()),m_nextshare(NULL),m_data(object.m_data){m_prevshare->m_nextshare=this;}

inline ~Object(){if(IsShared())UnlinkShare();else delete( m_data ); m_data = NULL;}

Object& operator=(const Object& object);

Object& operator+=(const Object& object);

inline Data GetData()const{return( *m_data);}

void SetData(const Data& data);

private:

inline bool IsShared()const{return(m_prevshare!=NULL m_nextshare!=NULL);}

Object& LocateLastShare()const;

Object* LocateShare(const Object & object)const;

void UnlinkShare();

mutable Object * m_nextshare;

mutable Object * m_prevshare;

Data * m_data;

};

// Friend function

ostream& operator<<(ostream& os, const Object& object)

{

os<<"Object:0x"<<&object<<"\t"<<*object.m_data;

return(os);

}

// Assign (implements shallow-copy)

Object& Object::operator=(const Object& object)

{

if( &object != this && // Not a self-reference.

!LocateShare(object) ) // Not already shared.

{

// Unlink or destroy data.

if( IsShared() )

UnlinkShare();

else if( m_data )

delete( m_data );

// Shallow-copy.

m_data = object.m_data;

// Link to new shares.

m_prevshare = &object.LocateLastShare();

m_prevshare->m_nextshare = this;

}

return(*this);

}

// Add/assign (implements deep-copy)

Object& Object::operator+=(const Object& object)

{

if( IsShared() )

{

UnlinkShare();

m_data = new Data( *m_data + *object.m_data );

}

else

*m_data += *object.m_data;

return( *this );

}

// Returns a reference to the last shared instance of this instance.

Object& Object::LocateLastShare()const

{

Object* p=(Object*)this;

while(p && p->m_nextshare)

p=p->m_nextshare;

return(*p);

}

// Returns a pointer to the given object if it is amongst the shared instances

// of this instance. Returns NULL if the object is this instance or is not shared.

Object* Object::LocateShare(const Object& object)const

{

// Search previous instances first.

Object* p=m_prevshare;

while( p && p!=&object)

p=p->m_prevshare;

if(!p)

{

// Not found, search next instances:

p = m_nextshare;

while( p && p!=&object) p=p->m_nextshare;

}

return(p);

}

// Unlinks this object from its shared instances.

void Object::UnlinkShare()

{

// Update the links on either side first.

if(m_nextshare) m_nextshare->m_prevshare=m_prevshare;

if(m_prevshare) m_prevshare->m_nextshare=m_nextshare;

m_nextshare=NULL;

m_prevshare=NULL;

}

// Mutator. Implements deep copy if incoming data differs.

void Object::SetData(const Data& data)

{

if( *m_data != data )

{

if( IsShared() )

{

UnlinkShare();

m_data = new Data(data);

}

else

*m_data = data;

}

}

// Demonstration program:

int main()

{

Object a;

a.SetData( 5 );

Object b = a; // Assign (lazy copy)

Object* c = new Object(b); // Copy construct (lazy copy)

cout<<"Original memory:"<<endl;

cout<<"a\t"<<a<<endl;

cout<<"b\t"<<b<<endl;

cout<<"c\t"<<*c<<endl;

cout<<endl;

b += a; // Deep copy.

cout<<"After mutating b:"<<endl;

cout<<"a\t"<<a<<endl;

cout<<"b\t"<<b<<endl;

cout<<"c\t"<<*c<<endl;

cout<<endl;

delete(c);

cout<<"After destroying c:"<<endl;

cout<<"a\t"<<a<<endl;

cout<<"b\t"<<b<<endl;

cout<<endl;

// Instantiate a new, unshared instance

c = new Object();

cout<<"After instantiating c as new:"<<endl;

cout<<"a\t"<<a<<endl;

cout<<"b\t"<<b<<endl;

cout<<"c\t"<<*c<<endl;

cout<<endl;

// Assign b to c

*c = b;

cout<<"After reassigning c:"<<endl;

cout<<"a\t"<<a<<endl;

cout<<"b\t"<<b<<endl;

cout<<"c\t"<<*c<<endl;

cout<<endl;

return(0);

}

Output:

Original memory:

a Object:0x001FFA20 Data:0x003577B8 (5)

b Object:0x001FFA0C Data:0x003577B8 (5)

c Object:0x00211F58 Data:0x003577B8 (5)

After mutating b:

a Object:0x001FFA20 Data:0x003577B8 (5)

b Object:0x001FFA0C Data:0x00357818 (10)

c Object:0x00211F58 Data:0x003577B8 (5)

After destroying c:

a Object:0x001FFA20 Data:0x003577B8 (5)

b Object:0x001FFA0C Data:0x00357818 (10)

After instantiating c as new:

a Object:0x001FFA20 Data:0x003577B8 (5)

b Object:0x001FFA0C Data:0x00357818 (10)

c Object:0x00211F58 Data:0x003578A8 (0)

After reassigning c:

a Object:0x001FFA20 Data:0x003577B8 (5)

b Object:0x001FFA0C Data:0x00357818 (10)

c Object:0x00211F58 Data:0x00357818 (10)

User Avatar

Wiki User

11y ago
This answer is:
User Avatar

Add your answer:

Earn +20 pts
Q: Example of lazy copy in c plus plus?
Write your answer...
Submit
Still have questions?
magnify glass
imp
Related questions

What is c plus c plus c plus c plus c?

c + c + c + c + c = 5 * c.


How do you concatinate two files in c plus plus?

Copy the first file then append the second file to the copy.


Example of binaray operator in c plus plus?

+ is an example, one of many, of a binary operator in C or C++ a = b + c; // for usage example


What are the Example Output of Calculator Program in C plus plus?

example output of c++ calculator


C program plus copy of string to another?

strcpy


Users can use a shortcut such as CTRL plus C for operations they perform frequently?

CTRL C to copy


What command is the control key plus c?

Copy the selected text (or object).


Is c plus plus an unstructured programming language?

No, BASIC is, for example.


Which operator cannot be overloaded c plus plus?

comma (,) is an example


Example of flowchart of while loop in c plus plus?

kk


Can you explain step by step how to use ctrl plus?

Assuming I understand your question: On an IBM PC keyboard there is a key labeled Ctrl which stands for Control. For a number of functions they will say Press Ctrl plus some other key. For example, Ctrl+C (sometimes written Ctrl-C) copies just like the copy function in the Edit menu. To copy using Ctrl+C, highlight the area you want to copy, press the Ctrl key and while holding it down, press the C key on the keyboard.


What is the use of print option in c plus plus?

C++ has no print option. The print option in your IDE allows you to print your C++ source code, thus giving you a "hard" copy of your code.