1. Introduktion

När vi skickar basdatatyper (int, float etc., ) till en funktion sker en kopia från det samtalskod till den kallade funktionen. Titta nu på kodkoden nedan som gör en enkel funktion:

 int AddNumbers (int loc_X, int loc_Y) {return (loc_X + loc_Y); } void main {int x = 5; int y = 3; int-resultat = AddNumbers (x, y); } 

Kopian jag tar sker mellan x => loc_X och y => loc_Y. Innehållet i variabel x i huvudfunktionsomfång kopieras till variabeln loc_X, som ligger i AddNumbers- funktionsomfånget. Detta gäller även för nästa parameter loc_Y. Denna kopiering visas nedan:

OK. Detta är bra för vanliga datatyper. En klass kan ha en eller flera dataledamöter. Hur kopian inträffar mellan datamedlemmarna är vad vi kommer att ta itu med detta nav. När navet fortskrider kommer jag att förklara grunt exemplar, djup kopia och behovet av vår egen kopieringskonstruktör .

2. ShalloC-klass

För att visa behovet av kopieringskonstruktören definierar vi först en exempelklass. Detta exempel är ShalloC . Denna klass innehåller endast en heltalspekare som privatdatamedlem som visas nedan:

 // Exempel 01: Privat data Medlem privat: int * x; 

Konstruktören skapar en minnesplats i en hög och kopierar det överförda i värdet m till höghalten. Den här koden visas nedan:

 // Prov 02: Konstruktör med en enda parameter ShalloC (int m) {x = nytt int; * x = m; } 

Funktionerna Hämta och ställa in används för att hämta värdet för heapminneinnehåll respektive Ställa in heapminnesinnehållet. Nedan är koden som ställer in och får värdet för heltalsheapminnet:

 // Prov 03: Get and Set Functions int GetX () const {return * x; } ogiltig SetX (int m) {* x = m; } 

Slutligen finns det en funktion för att skriva ut värdet för höginnehåll i konsolfönstret. Funktionen visas nedan:

 // Exempel 04: Print Function void PrintX () {cout << "Int X =" << * x << endl; } 

Nu kan du få uppfattningen om vad ShalloC- klassen kommer att göra. För närvarande har den en konstruktör som skapar ett högminne och i destruktorn rensar vi minnet skapat som visas i koden nedan:

 // Prov 05: Avlägsna högen ~ ShalloC () {ta bort x; } 

3. Kort kopia kontra djup kopia

I programmets huvud skapade vi två objekt ob1 och ob2. Objektet ob2 skapas med kopieringskonstruktören. På vilket sätt? Och var är "kopia-konstruktören".? Om du tittar på uttalandet ShalloC ob2 = ob1; du vet tydligt att ob2 ännu inte är skapad och under tiden ob1 redan skapats. Därför åberopas en kopieringskonstruktör. Trots att kopieringskonstruktören inte är implementerad kommer kompilatorn att tillhandahålla standardkopieringskonstruktör. När båda objekten har skapats skriver vi ut värdena i ob1 och ob2.

 // Exempel 06: Skapa objekt 1 och kopiera det till objekt 2. // Skriv ut dataleden för både objekt 1 och 2. ShalloC ob1 (10); ShalloC ob2 = ob1; ob1.PrintX (); ob2.PrintX (); 

Efter att ha skrivit ut värdena i ob1 och ob2 ändrar vi värdet på objektet ob1s datamedlem pekade värde till 12. Därefter skrivs både värdena på ob1 och ob2 ut. Koden och dess utgång visas nedan:

 // Exempel 07: Ändra värdet för dataleden för objekt 1 // Och skriv ut både objekt 1 och objekt 2 ob1.SetX (12); ob1.PrintX (); ob2.PrintX (); 

Utgången visar värde 12 för både ob1 och ob2. Överraskande ändrade vi bara dataleden för objektet ob1. Sedan, varför ändringarna återspeglas på båda föremålen? Detta är vad som kallas grunt exemplar inducerat av kompilatorn som standardkonstruktör. För att förstå denna titt på bilden nedan:

När objekt ob1 skapas tilldelas minnet för att lagra ett heltal i högen. Låt oss anta att heapminnesplatsadressen är 0x100B. Den här adressen är det som lagras i x. Kom ihåg att x är en heltalspekare. Värdet lagrat i pekvariabeln x är adressen 0x100B och innehållet i adressen 0x100B är värde 10. I exemplet vill vi ta itu med innehållet i adressen 0x100B vi använder pekaren som refererar till som * x . Kompilatorn tillhandahöll kopieringskonstruktör kopierar adressen lagrad i ob1 (x) till ob2 (x). Efter kopian pekar båda pekarna i ob1 och ob2 på samma objekt. Så att ändra 0x100B genom ob1.SetX (12) återspeglas tillbaka i ob2. Nu fick du hur resultatet är att skriva ut 12 för både objekten ob1 och ob2.

Hur undviker vi ovanstående problem? Vi bör utföra den djupa kopian genom att implementera vår egen kopieringskonstruktör. Så en användardefinierad kopieringskonstruktör krävs för att undvika problemet med grunt kopia. Nedan är kopieringskonstruktören:

 // Exempel 08: Presentera Copy Constructor och utför Deep Copy ShalloC (const ShalloC & obj) {x = new int; * x = obj.GetX (); } 

När vi injicerar denna kopieringskonstruktör till ShalloC-klassen pekar inte x-pekaren i objektet ob2 på samma högplats 0x100B. Uttalandet x = nytt int; skapar den nya heap-platsen och kopierar sedan värdet på obj-innehåll till den nya heap-platsen. Utgången från programmet, efter att ha introducerat vår egen kopieringskonstruktör, visas nedan:

Hela koden visas nedan:

 // TestIt.cpp: Definierar ingångspunkten för konsolapplikationen. // #include "stdafx.h" #include att använda namespace std; klass ShalloC {// Exempel 01: Privat data Medlem privat: int * x; public: // Exempel 02: Konstruktör med en enda parameter ShalloC (int m) {x = new int; * x = m; } // Exempel 08: presentera Copy Constructor och utför Deep Copy ShalloC (const ShalloC & obj) {x = new int; * x = obj.GetX (); } // Exempel 03: Get and Set Functions int GetX () const {return * x; } ogiltig SetX (int m) {* x = m; } // Exempel 04: Utskriftsfunktion ogiltig PrintX () {cout << "Int X =" << * x << endl; } // Exempel 05: Avlägsna högen ~ ShalloC () {ta bort x; }}; int main () {// Exempel 06: Skapa objekt 1 och kopiera det till objekt 2. // Skriv ut datormedlemmen för både objekt 1 och 2. ShalloC ob1 (10); ShalloC ob2 = ob1; ob1.PrintX (); ob2.PrintX (); // Exempel 07: Ändra värdet för dataleden för objekt 1 // Och skriv ut både objekt 1 och objekt 2 ob1.SetX (12); ob1.PrintX (); ob2.PrintX (); }