Jaka jest różnica między kopią głęboką a płytką?
Jaka jest różnica między kopią głęboką a płytką?
Odpowiedzi:
Płytkie kopie powielają jak najmniej. Płytka kopia kolekcji jest kopią struktury kolekcji, a nie elementów. Dzięki płytkiej kopii dwie kolekcje dzielą teraz poszczególne elementy.
Głębokie kopie duplikują wszystko. Głęboka kopia kolekcji to dwie kolekcje ze zduplikowanymi wszystkimi elementami oryginalnej kolekcji.
Szerokość vs głębokość; myśl w kategoriach drzewa odniesień z twoim obiektem jako węzłem głównym.
Płycizna:
Zmienne A i B odnoszą się do różnych obszarów pamięci, gdy B jest przypisane do A, dwie zmienne odnoszą się do tego samego obszaru pamięci. Późniejsze modyfikacje zawartości jednego z nich są natychmiast odzwierciedlane w treści innych, ponieważ udostępniają zawartość.
Głęboki:
Zmienne A i B odnoszą się do różnych obszarów pamięci, gdy B jest przypisane do A, wartości w obszarze pamięci, na które wskazuje A, są kopiowane do obszaru pamięci, na który wskazuje B. Późniejsze modyfikacje zawartości albo pozostają unikalne dla A lub B; zawartość nie jest udostępniana.
Krótko mówiąc, zależy to od tego, co wskazuje na co. W płytkiej kopii obiekt B wskazuje lokalizację obiektu A w pamięci. W głębokiej kopii wszystkie rzeczy w lokalizacji pamięci obiektu A są kopiowane do lokalizacji pamięci obiektu B.
Ten artykuł wiki ma świetny schemat.
Spróbuj rozważyć następujący obraz
Na przykład Object.MemberwiseClone tworzy płytkie łącze do kopiowania
i za pomocą interfejsu ICloneable możesz uzyskać głęboką kopię, jak opisano tutaj
Specjalnie dla programistów iOS:
Jeśli B
jest to płytkie kopia z A
, a następnie do pierwotnych danych to jak B = [A assign];
i dla obiektów to jak B = [A retain]
;
B i A wskazują na to samo miejsce w pamięci
Jeśli B
jest głęboka kopia z A
, to jest jakB = [A copy];
B i A wskazują różne lokalizacje pamięci
Adres pamięci B jest taki sam jak adresu A.
B ma taką samą zawartość jak A
Płytka kopia: Kopiuje wartości składowe z jednego obiektu do drugiego.
Głębokie kopiowanie: Kopiuje wartości składowe z jednego obiektu do drugiego.
Wszelkie obiekty wskaźnika są powielane i głęboko kopiowane.
Przykład:
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.)
Nie widziałem tutaj krótkiej, łatwej do zrozumienia odpowiedzi - spróbuję.
W przypadku płytkiej kopii każdy obiekt wskazywany przez źródło jest również wskazywany przez miejsce docelowe (tak, aby żadne obiekty odniesienia nie były kopiowane).
W przypadku głębokiej kopii każdy obiekt wskazywany przez źródło jest kopiowany, a kopia jest wskazywana przez miejsce docelowe (więc będą teraz 2 każdego obiektu odniesienia). Powtarza się w dół drzewa obiektów.
Aby ułatwić zrozumienie, możesz śledzić ten artykuł: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
Płytka kopia:
Głęboka kopia:
{Wyobraź sobie dwa obiekty: A i B tego samego typu _t (w odniesieniu do C ++) i myślisz o płytkim / głębokim kopiowaniu A do B}
Płytka kopia: po prostu tworzy kopię odwołania do A w B. Pomyśl o tym jak o kopii adresu A. Tak więc adresy A i B będą takie same, tzn. Będą wskazywać tę samą lokalizację pamięci, tj. Zawartość danych.
Głęboka kopia: po prostu tworzy kopię wszystkich członków A, przydziela pamięć w innym miejscu dla B, a następnie przypisuje skopiowane elementy do B w celu uzyskania głębokiej kopii. W ten sposób, jeśli A stanie się nieistniejące, B jest nadal ważne w pamięci. Prawidłowym terminem byłoby klonowanie, jeśli wiesz, że oba są całkowicie takie same, ale jednak różne (tj. Przechowywane jako dwie różne jednostki w przestrzeni pamięci). Możesz także podać swoje opakowanie klonu, w którym możesz zdecydować za pomocą listy włączenia / wyłączenia, które właściwości wybrać podczas głębokiego kopiowania. Jest to dość powszechna praktyka podczas tworzenia interfejsów API.
Możesz wykonać płytką kopię TYLKO_Jeśli rozumiesz związane z nią stawki. Kiedy masz ogromną liczbę wskaźników, którymi trzeba się posługiwać w C ++ lub C, robienie płytkiej kopii obiektu jest NAPRAWDĘ złym pomysłem.
PRZYKŁAD_OF_DEEP KOPIA_ Przykładem jest, gdy próbujesz wykonać przetwarzanie obrazu i rozpoznawanie obiektu, musisz zamaskować „Nieistotny i powtarzalny ruch” poza obszarami przetwarzania. Jeśli korzystasz ze wskaźników obrazu, możesz mieć specyfikację zapisywania obrazów maski. TERAZ ... jeśli zrobisz płytką kopię obrazu, gdy referencje wskaźnika zostaną ZABIJANE ze stosu, utracisz referencję i jej kopię, tzn. W pewnym momencie wystąpi błąd w czasie wykonywania naruszenia dostępu. W takim przypadku potrzebujesz głębokiej kopii obrazu, KLONUJĄC go. W ten sposób możesz odzyskać maski na wypadek, gdyby były potrzebne w przyszłości.
EXAMPLE_OF_SHALLOW_COPY Nie jestem bardzo kompetentny w porównaniu do użytkowników w StackOverflow, więc możesz usunąć tę część i dać dobry przykład, jeśli możesz to wyjaśnić. Ale naprawdę uważam, że nie jest dobrym pomysłem wykonywanie płytkich kopii, jeśli wiesz, że twój program będzie działał przez nieskończony okres czasu, tj. Ciągła operacja „push-pop” na stosie z wywołaniami funkcji. Jeśli demonstrujesz coś amatorowi lub nowicjuszowi (np. Samouczki C / C ++), prawdopodobnie jest to w porządku. Ale jeśli korzystasz z aplikacji, takiej jak system nadzoru i wykrywania lub Sonar Tracking System, nie powinieneś ciągle kopiować swoich obiektów, ponieważ prędzej czy później zabije Twój program.
char * Source = "Hello, world.";
char * ShallowCopy = Source;
char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);
„ShallowCopy” wskazuje to samo miejsce w pamięci, co „Source”. „DeepCopy” wskazuje na inną lokalizację w pamięci, ale zawartość jest taka sama.
Co to jest Shallow Copy?
Płytka kopia to nieco mądra kopia obiektu. Tworzony jest nowy obiekt, który ma dokładną kopię wartości w oryginalnym obiekcie. Jeśli którekolwiek z pól obiektu są odwołaniami do innych obiektów, kopiowane są tylko adresy referencyjne, tzn. Kopiowany jest tylko adres pamięci.
Na tym rysunku MainObject1
ma pola field1
typu int i ContainObject1
typu ContainObject
. Kiedy zrobisz płytką kopię MainObject1
, MainObject2
tworzony jest z field2
zawartością skopiowanej wartości field1
i nadal wskazuje na ContainObject1
siebie. Zauważ, że skoro field1
jest typu pierwotnego, jego wartość jest kopiowana, field2
ale ponieważ ContainedObject1
jest obiektem, MainObject2
nadal wskazuje ContainObject1
. Tak więc wszelkie zmiany wprowadzone ContainObject1
w MainObject1
zostaną odzwierciedlone w MainObject2
.
Teraz, jeśli jest to płytka kopia, zobaczmy, co to jest głęboka kopia?
Co to jest Deep Copy?
Głęboka kopia kopiuje wszystkie pola i tworzy kopie dynamicznie alokowanej pamięci wskazanej przez pola. Głęboka kopia występuje, gdy obiekt jest kopiowany wraz z obiektami, do których się odnosi.
Na tym rysunku obiekt MainObject1 ma pola field1
typu int i ContainObject1
typu ContainObject
. Po wykonaniu głębokiej kopii MainObject1
, MainObject2
jest tworzony z field2
zawartością skopiowanej wartości field1
i ContainObject2
z wartością skopiowanej wartości ContainObject1
. Uwaga: wszelkie zmiany wprowadzone w ContainObject1
w MainObject1
nie będą odzwierciedlone w MainObject2
.
field3
której, gdy jesteś w stanie spróbować zrozumieć coś tak głębokiego jak ten problem, gdzie jest to, że # 3 w tym przykładzie ma miejsce ContainObject2
?
W programowaniu obiektowym typ zawiera zbiór pól składowych. Te pola mogą być przechowywane albo według wartości, albo przez odniesienie (tj. Wskaźnik do wartości).
W płytkiej kopii tworzona jest nowa instancja tego typu, a wartości są kopiowane do nowej instancji. Wskaźniki odniesienia są również kopiowane tak jak wartości. Dlatego odniesienia odnoszą się do oryginalnych obiektów. Wszelkie zmiany elementów składowych, które są przechowywane przez odniesienie, pojawiają się zarówno w oryginale, jak i kopii, ponieważ nie wykonano żadnej kopii obiektu odniesienia.
W głębokiej kopii pola przechowywane według wartości są kopiowane jak poprzednio, ale wskaźniki do obiektów przechowywanych przez odniesienie nie są kopiowane. Zamiast tego tworzona jest głęboka kopia obiektu, do którego istnieje odniesienie, i zapisywany jest wskaźnik do nowego obiektu. Wszelkie zmiany wprowadzone do tych obiektów, do których istnieją odniesienia, nie wpłyną na inne kopie obiektu.
„ShallowCopy” wskazuje to samo miejsce w pamięci, co „Source”. „DeepCopy” wskazuje na inną lokalizację w pamięci, ale zawartość jest taka sama.
Płytkie klonowanie:
definicja: „ Płytka kopia obiektu kopiuje obiekt„ główny ”, ale nie kopiuje obiektów wewnętrznych.” Kiedy obiekt niestandardowy (np. Pracownik) ma po prostu prymitywne, zmienne typu String, wówczas używasz Shallow Cloning.
Employee e = new Employee(2, "john cena");
Employee e2=e.clone();
Wracasz super.clone();
w zastąpionej metodzie clone () i twoje zadanie się kończy.
Głębokie klonowanie :
definicja: „W przeciwieństwie do płytkiej kopii, głęboka kopia jest w pełni niezależną kopią obiektu”.
Oznacza, że obiekt pracownika zawiera inny obiekt niestandardowy:
Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");
Następnie musisz napisać kod, aby sklonować obiekt „Adres” również w przesłoniętej metodzie clone (). W przeciwnym razie obiekt Adres nie zostanie sklonowany i spowoduje błąd, gdy zmienisz wartość Adres w sklonowanym obiekcie pracownika, co również odzwierciedla pierwotny.
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
Deep Copy
Głęboka kopia kopiuje wszystkie pola i tworzy kopie dynamicznie alokowanej pamięci wskazanej przez pola. Głęboka kopia występuje, gdy obiekt jest kopiowany wraz z obiektami, do których się odnosi.
Płytka kopia
Płytka kopia to nieco mądra kopia obiektu. Tworzony jest nowy obiekt, który ma dokładną kopię wartości w oryginalnym obiekcie. Jeśli którekolwiek z pól obiektu są odwołaniami do innych obiektów, kopiowane są tylko adresy referencyjne, tzn. Kopiowany jest tylko adres pamięci.
Płytka kopia - zmienna odniesienia wewnątrz oryginalnych i płytko skopiowanych obiektów ma odniesienie do wspólnego obiektu.
Głębokie kopiowanie - zmienna odniesienia w oryginalnych i głęboko skopiowanych obiektach ma odniesienie do innego obiektu.
klon zawsze wykonuje płytką kopię.
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();
}
}
główna klasa jest następująca-
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 powyżej będzie-
fałsz prawda prawda
fałszywy fałszywy fałszywy
Wszelkie zmiany dokonane w obiekcie pierwotnym będą odzwierciedlone w obiekcie płytkim, a nie w obiekcie głębokim.
list.get(0).name="ViSuaLBaSiC";
System.out.println(shallow.get(0).getName()+" "+deep.get(0).getName());
OutPut- ViSuaLBaSiC C
Chciałbym podać przykład zamiast formalnej definicji.
var originalObject = {
a : 1,
b : 2,
c : 3,
};
Ten kod pokazuje płytką kopię :
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
Ten kod pokazuje głęboką kopię :
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 !!
1 1 4 4 4 4 4 4
Mówiąc najprościej, płytka kopia jest podobna do funkcji Call by Reference, a głęboka kopia jest podobna do funkcji Call by Value
W Call By Reference zarówno formalne, jak i rzeczywiste parametry funkcji odnoszą się do tej samej lokalizacji w pamięci i wartości.
W Call By Value zarówno formalne, jak i rzeczywiste parametry funkcji odnoszą się do innej lokalizacji pamięci, ale mają tę samą wartość.
Płytka kopia konstruuje nowy obiekt złożony i wstawia do niego swoje odniesienia do oryginalnego obiektu.
W przeciwieństwie do płytkiej kopii, kopiowanie głębokie konstruuje nowy obiekt złożony, a także wstawia kopie oryginalnych obiektów oryginalnego obiektu złożonego.
Weźmy przykład.
import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)
Powyższy kod drukuje FAŁSZ.
Zobaczmy jak.
Oryginalny obiekt złożony x=[1,[2]]
(nazywany jako obiekt złożony, ponieważ ma obiekt wewnątrz obiektu (Inception))
jak widać na obrazku, wewnątrz listy znajduje się lista.
Następnie tworzymy jego płytką kopię za pomocą y = copy.copy(x)
. To, co robi tutaj Python, spowoduje utworzenie nowego obiektu złożonego, ale obiekty wewnątrz niego wskazują na obiekty orignalne.
Na obrazie utworzono nową kopię dla listy zewnętrznej. ale wewnętrzna lista pozostaje taka sama jak oryginalna.
Teraz tworzymy jego kopię za pomocą z = copy.deepcopy(x)
. to, co robi tutaj Python, utworzy nowy obiekt zarówno dla listy zewnętrznej, jak i wewnętrznej. jak pokazano na poniższym obrazku (podświetlone na czerwono).
Na końcu drukowany jest kod False
, ponieważ y i z nie są tymi samymi obiektami.
HTH.
Płytkie kopiowanie polega na utworzeniu nowego obiektu, a następnie skopiowaniu niestatycznych pól bieżącego obiektu na nowy obiekt. Jeśli pole jest typem wartości -> wykonywana jest kopia pola po kawałku; dla typu referencji -> referencja jest kopiowana, ale obiekt referencyjny nie jest; dlatego oryginalny obiekt i jego klon odnoszą się do tego samego obiektu.
Głębokie kopiowanie polega na utworzeniu nowego obiektu, a następnie skopiowaniu niestatycznych pól bieżącego obiektu na nowy obiekt. Jeśli pole jest typem wartości -> wykonywana jest kopia pola po kawałku. Jeśli pole jest typem odniesienia -> wykonywana jest nowa kopia obiektu, do którego następuje odwołanie . Klonowane klasy muszą zostać oznaczone jako [Serializable].
Zaczerpnięte z [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Głęboka kopia polega na użyciu zawartości jednego obiektu do utworzenia kolejnego wystąpienia tej samej klasy. W głębokiej kopii dwa obiekty mogą zawierać tę samą informację, ale obiekt docelowy będzie miał własne bufory i zasoby. zniszczenie jednego z obiektów nie wpłynie na pozostały obiekt. Przeciążony operator przypisania utworzyłby głęboką kopię obiektów.
Płytka kopia polega na skopiowaniu zawartości jednego obiektu do innej instancji tej samej klasy, tworząc w ten sposób odbicie lustrzane. Dzięki prostemu kopiowaniu odniesień i wskaźników oba obiekty będą dzielić tę samą zewnętrznie zawartą zawartość drugiego obiektu, aby były nieprzewidywalne.
Wyjaśnienie:
Za pomocą konstruktora kopiowania po prostu kopiujemy wartości danych członek po członku. Ta metoda kopiowania nazywa się płytką kopią. Jeśli obiekt jest prostą klasą, złożoną z wbudowanych typów i bez wskaźników, byłoby to do przyjęcia. Ta funkcja użyłaby wartości i obiektów, a jej zachowanie nie byłoby zmienione płytką kopią, kopiowane są tylko adresy wskaźników będących członkami, a nie wartość, na którą wskazuje adres. Wartości danych obiektu zostałyby wówczas przypadkowo zmienione przez funkcję. Gdy funkcja wykracza poza zakres, kopia obiektu wraz ze wszystkimi danymi jest usuwana ze stosu.
Jeśli obiekt ma jakieś wskaźniki, należy wykonać głęboką kopię. W przypadku głębokiej kopii obiektu pamięć jest przydzielana dla obiektu w magazynie wolnym, a wskazane elementy są kopiowane. Głęboka kopia jest używana dla obiektów zwracanych z funkcji.
Aby dodać więcej do innych odpowiedzi,
Płytka kopia nie utworzy nowego odwołania, ale głęboka kopia utworzy nowe odniesienie.
Oto program wyjaśniający głęboką i płytką kopię.
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 + "]";
}
}
Kopiowanie ararysów:
Tablica jest klasą, co oznacza, że jest typem referencyjnym, więc tablica1 = tablica2 daje dwie zmienne, które odwołują się do tej samej tablicy.
Ale spójrz na ten przykład:
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]);
}
płytki klon oznacza, że kopiowana jest tylko pamięć reprezentowana przez sklonowaną tablicę.
Jeśli tablica zawiera obiekty typu wartości, wartości są kopiowane ;
jeśli tablica zawiera typ referencji, kopiowane są tylko referencje - w rezultacie istnieją dwie tablice, których członkowie odwołują się do tych samych obiektów .
Aby utworzyć głęboką kopię - w której powielone są typy referencji, należy zapętlić tablicę i ręcznie sklonować każdy element.
private void button1_Click(object sender, EventArgs e) { int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{6,7,8,9,0}; MessageBox.Show(arr1[2] + " " + arr2[2]); arr2 = arr1; MessageBox.Show(arr1[2] + " " + arr2[2]); arr1[2] = 12; MessageBox.Show(arr1[2] + " " + arr2[2]); }
Zrozumiałem z następujących wierszy.
Płytka kopia kopiuje pola typu wartości obiektu (int, float, bool) do obiektu docelowego, a typy referencyjne obiektu (ciąg znaków, klasa itp.) Są kopiowane jako odwołania do obiektu docelowego. W tym docelowym typie odniesienia będą wskazywać lokalizację pamięci obiektu źródłowego.
Głęboka kopia kopiuje wartość obiektu i typy referencji do kompletnej nowej kopii obiektów docelowych. Oznacza to, że zarówno typy wartości, jak i typy referencyjne zostaną przydzielone nowe lokalizacje pamięci.
Dodając do wszystkich powyższych definicji, jeszcze jedną i najczęściej używaną głęboką kopię, znajduje się w konstruktorze kopii (lub przeciążającym operatorze przypisania) klasy.
Płytka kopia -> ma miejsce, gdy nie udostępniasz konstruktora kopii. Tutaj kopiowany jest tylko obiekt, ale nie wszyscy członkowie klasy są kopiowani.
Głębokie kopiowanie -> ma miejsce, gdy zdecydujesz się na implementację konstruktora kopiowania lub przypisanie przeciążenia w swojej klasie i pozwala na skopiowanie wszystkich członków klasy.
MyClass& MyClass(const MyClass& obj) // copy constructor for MyClass
{
// write your code, to copy all the members and return the new object
}
MyClass& operator=(const MyClass& obj) // overloading assignment operator,
{
// write your code, to copy all the members and return the new object
}
Konstruktor kopiowania służy do inicjalizacji nowego obiektu za pomocą wcześniej utworzonego obiektu tej samej klasy. Domyślnie kompilator napisał płytką kopię. Płytka kopia działa dobrze, gdy dynamiczna alokacja pamięci nie jest zaangażowana, ponieważ gdy dynamiczna alokacja pamięci jest zaangażowana, oba obiekty będą wskazywały tę samą lokalizację pamięci na stercie, dlatego aby usunąć ten problem, napisaliśmy głęboką kopię, aby oba obiekty miały własną kopię atrybutów w pamięci. Aby przeczytać szczegóły z pełnymi przykładami i objaśnieniami, możesz przeczytać konstruktory w artykule C ++ .