В чем разница между глубокой копией и мелкой копией?

В чем разница между глубокой копией и мелкой копией?


person David Locke    schedule 08.10.2008    source источник


Ответы (30)


Мелкие копии как можно меньше дублируют. Неглубокая копия коллекции - это копия структуры коллекции, а не элементов. С мелкой копией две коллекции теперь разделяют отдельные элементы.

Глубокие копии все дублируют. Глубокая копия коллекции - это две коллекции, в которых все элементы исходной коллекции продублированы.

person S.Lott    schedule 08.10.2008
comment
Может быть реализация .NET MemberwiseClone () делает больше, чем обычное копирование в обычном смысле. - person Lu55; 19.10.2012
comment
Имейте в виду, что существуют также смешанные копии (не только такие, как ленивое копирование), который дублирует только его часть (вот экземпляр)! ;) - person cregox; 10.01.2015
comment
Итак, неглубокая копия X может изменять элементы в X, а глубокая копия - нет? - person punstress; 24.08.2015
comment
что такое структура коллекции? - person Honey; 12.04.2016
comment
Коллекции @Honey могут представлять собой различные структуры данных, в которых хранится несколько элементов данных. В python у нас есть кортеж, список, словари и т. Д. - person Murphy; 09.08.2016
comment
Как и большинство вещей, это немного зависит от языка. Например, определение мелких копий в JavaScript - это копирование всех примитивных значений и создание ссылок на объекты. - person Govind Rai; 16.01.2017
comment
@AugustinePA, это зависит от характера коллекции. Если вы, например, сделаете неглубокую копию int[] в Java, элементы действительно будут скопированы. - person aioobe; 19.03.2018
comment
@RoyiNamir Вы, вероятно, уже поняли это за последние 7 лет, но для всех, кто интересуется этим: мелкая копия копирует тип значения бит за битом правильно, но это немного сбивает с толку. Если у вас есть объект Customer, который имеет объект Address, побитовое копирование объекта Customer означает, что копируется указатель / ссылка на объект Address. Оригинал и копия указывают на один и тот же объект Address, тогда как глубокая копия создаст новый объект Address и будет указывать на него. - person Raphael Schmitz; 21.02.2019
comment
Также см. Этот ответ и этот ответьте за примерами. - person chetan; 11.06.2020

Ширина vs глубина; представьте себе дерево ссылок с вашим объектом в качестве корневого узла.

Мелкий:

Перед копированиемНеглубокое копирование Неглубокое копирование

Переменные A и B относятся к разным областям памяти, когда B назначается A, две переменные относятся к одной и той же области памяти. Более поздние изменения содержимого одного из них мгновенно отражаются на содержимом другого, поскольку они совместно используют содержимое.

Глубокий:

Перед копированиемГлубокое копирование Глубокое копирование

Переменные A и B относятся к различным областям памяти, когда B назначается A, значения в области памяти, на которую указывает A, копируются в область памяти, на которую указывает B. Более поздние модификации содержимого остаются уникальными для A или B; содержимое не передается.

person dlamblin    schedule 08.10.2008
comment
Вот статья в Википедии, из которой взята эта иллюстрация, на случай, если она не имеет для вас смысла вне контекста en.wikipedia.org/wiki/Object_copy#Shallow_copy - person corbin; 07.11.2013
comment
В случае неглубокой копии, если мы внесем какие-либо изменения в массив B, будет ли это отражено в массиве A, поскольку оба A и B указывают на одно и то же место в памяти? - person tek3; 16.01.2015
comment
Таким образом, неглубокая копия означает, что для так называемой копии доступна только ссылка на исходный объект. Любые изменения в исходной сущности будут скопированы в новую? Глубокая копия клонирует исходный объект и создает новую несвязанную копию. - person Swanidhi; 25.03.2016
comment
В одной строке его копия по ссылке vs копия по значению. Не уверен, что ответ правильный! - person mannuscript; 05.06.2017
comment
изображения взяты непосредственно из Википедии без цитирования - person jasonleonhard; 05.09.2017
comment
@jasonleonhard Итак, 9 лет назад я просто помещал URL-адреса к изображениям, потому что встраивание изображений не поддерживалось. Таким образом, URL ссылался на свой источник. Позже сообщество превратило URL-адреса во встроенные изображения без редактирования каких-либо ссылок на них. Верхний комментарий 4-летней давности также указывает на то, на что вы указываете. Взгляните: stackoverflow.com/posts/184780/revisions Почему бы просто не отредактировать цитату в ответе самостоятельно? Я могу быть недоступен в следующий раз, когда кто-то пожалуется на мой 10-летний стиль письма. - person dlamblin; 07.09.2017
comment
Конечно, я добавлю цитату, которую вы остановили. Независимо от человека, я буду продолжать сообщать, если я увижу, что кто-то использует чужую работу без ссылки, потому что это правильный поступок. Хотя, справедливости ради вашего ответа, вы могли бы добавить цитату так же быстро, как и написать ответ. Это хороший способ цитировать источники, которые вам не принадлежат в принципе. С наилучшими пожеланиями. - person jasonleonhard; 07.09.2017
comment
Для переменных A и B, когда B присваивается A, не означает ли это, что A = B в коде? Я как-то запутался, так как изображение отражает B = A. - person Peter Guan; 19.09.2018
comment
Как предлагает @Mannu, этот ответ объясняет копирование по ссылке и копирование по значению. Концепция мелкого и глубокого копирования применима к коллекциям, которые имеют ссылки в качестве элементов. Если элементы как старого, так и нового массивов являются ссылками на одни и те же объекты, то это неглубокая копия. Если ссылки разыменованы для создания новых объектов, то это глубокая копия. В основном, если новые объекты создаются рекурсивно, то это глубокая копия. Это то, что объясняется в принятом ответе. Этот ответ хорошо объясняет это на примерах. - person chetan; 11.06.2020
comment
@chetanraina полностью согласен, просто объект представляет собой коллекцию 0 порядка. То, что вы делаете с объектом (копирование ссылки или значения), применимо к каждой части коллекции при применении поверхностного или глубокого копирования соответственно. Я старался сделать его очень кратким, как краткое изложение статьи в Википедии, которую легко найти, или, может быть, чьей-то страницы из учебника. - person dlamblin; 16.06.2020
comment
@dlamblin нет проблем, пока мы говорим об отдельных объектах, которые не являются коллекциями. Но это неправильно в контексте коллекций. Если мы рассмотрим копирование коллекций, то то, что вы показали как глубокую копию, на самом деле является мелкой копией (обе коллекции имеют одинаковые ссылки X1, X2, X3), а то, что вы показали как мелкую копию, на самом деле не копируется, потому что копия не была создана, только новая ссылка была присвоена Б. - person chetan; 17.06.2020
comment
@PeterGuan Это зависит от того, как вы на это смотрите. При нынешней формулировке оба могут быть правдой. Если у меня есть поле A и поле B, выражение B, присвоенное A, не имеет большого смысла. В ответе автор имел в виду, что B присваивается содержанию A, где содержание является ссылкой на некоторую структуру. (содержание A присваивается B, также будет работать, но это противоречит ответу здесь.) - person 3limin4t0r; 05.08.2020

Короче говоря, это зависит от того, что на что указывает. В неглубокой копии объект B указывает на местоположение объекта A в памяти. При глубоком копировании все вещи в ячейке памяти объекта A копируются в ячейку памяти объекта B.

В этой вики-статье есть отличная диаграмма.

http://en.wikipedia.org/wiki/Object_copy

person helloandre    schedule 08.10.2008

Попробуйте рассмотреть следующее изображение

введите описание изображения здесь

Например, Object.MemberwiseClone создает мелкую копию ссылка

а с помощью интерфейса ICloneable вы можете получить глубокую копию, как описано здесь

person Alexandr    schedule 15.06.2016
comment
Одна картинка стоит тысячи слов. - person Levi Fuller; 26.06.2016
comment
О, мальчик, пришел сюда, чтобы узнать значение. Это единственный ответ, который помог. - person Karan Singh; 16.06.2017
comment
Это самый простой вариант, но он показывает только то, что необходимо. - person hina10531; 19.03.2018
comment
лучшая иллюстрация - person Muhammad Nayab; 22.01.2019
comment
Этот ответ объясняет копирование по ссылке и копирование по значению. Неглубокая копия против глубокой копии - это концепция, которая применяется к коллекциям. См. Этот ответ и этот ответ. - person chetan; 11.06.2020
comment
Эта концепция применима не только к коллекциям. - person nardnob; 06.12.2020

Специально для разработчиков iOS:

Если B является мелкой копией A, то для примитивных данных это похоже на B = [A assign];, а для объектов это похоже на B = [A retain];

B и A указывают на одну и ту же ячейку памяти

Если B является глубокой копией A, то это похоже на B = [A copy];

B и A указывают на разные участки памяти

Адрес памяти B такой же, как у A

B имеет то же содержимое, что и A

person Abhishek Bedi    schedule 23.01.2013
comment
Адрес памяти B такой же, как у A. Почему? - person ; 26.10.2015
comment
В Deep Copy адрес памяти B НЕ совпадает с адресом A - person ismail baig; 08.05.2018

Неглубокая копия: копирует значения членов из одного объекта в другой.

Глубокое копирование: копирует значения членов из одного объекта в другой.
Любые объекты-указатели дублируются и копируются глубоко.

Пример:

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.)
person Martin York    schedule 08.10.2008

Для простоты понимания вы можете прочитать эту статью: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm


Мелкая копия:

Мелкая копия


Глубокая копия:

Deep Copy

person Touchstone    schedule 19.03.2014

Я не видел здесь короткого, простого для понимания ответа, поэтому я попробую.

При неглубокой копии любой объект, на который указывает источник, также указывается адресатом (так что никакие ссылочные объекты не копируются).

При глубокой копии любой объект, на который указывает источник, копируется, а копия указывается адресатом (так что теперь будет 2 объекта каждого ссылочного объекта). Это повторяется вниз по дереву объектов.

person Bill K    schedule 08.10.2008

{Представьте два объекта: A и B одного типа _t (по отношению к C ++), и вы думаете о поверхностном / глубоком копировании A в B}

Неглубокая копия: просто копирует ссылку на А в Б. Думайте об этом как о копии адреса А. Таким образом, адреса A и B будут одинаковыми, то есть они будут указывать на одно и то же место в памяти, то есть на содержимое данных.

Глубокая копия: просто делает копию всех членов A, выделяет память в другом месте для B, а затем назначает скопированные элементы B для получения глубокой копии. Таким образом, если A становится несуществующим, B все еще действует в памяти. Правильный термин для использования - клонирование, когда вы знаете, что они оба полностью одинаковы, но все же разные (т.е. хранятся как два разных объекта в пространстве памяти). Вы также можете предоставить свою оболочку клона, где через список включения / исключения вы можете решить, какие свойства выбрать во время глубокого копирования. Это довольно распространенная практика при создании API.

Вы можете сделать мелкую копию ТОЛЬКО_Если вы понимаете, на какие ставки это нужно. Когда у вас есть огромное количество указателей на C ++ или C, делать неглубокую копию объекта - ДЕЙСТВИТЕЛЬНО плохая идея.

EXAMPLE_OF_DEEP COPY_ Например, когда вы пытаетесь выполнить обработку изображений и распознавание объектов, вам необходимо замаскировать «нерелевантное и повторяющееся движение» из областей обработки. Если вы используете указатели изображений, у вас может быть спецификация для сохранения этих изображений-масок. СЕЙЧАС ... если вы делаете неглубокую копию изображения, когда ссылки указателя УБИВАЮТСЯ из стека, вы потеряли ссылку и ее копию, т.е. в какой-то момент произойдет ошибка времени выполнения, связанная с нарушением доступа. В этом случае вам нужна глубокая копия вашего изображения путем КЛОНИРОВАНИЯ. Таким образом, вы можете получить маски, если они вам понадобятся в будущем.

EXAMPLE_OF_SHALLOW_COPY Я не очень хорошо осведомлен по сравнению с пользователями в StackOverflow, поэтому не стесняйтесь удалить эту часть и привести хороший пример, если вы можете уточнить. Но я действительно думаю, что делать неглубокое копирование - не лучшая идея, если вы знаете, что ваша программа будет работать в течение бесконечного периода времени, то есть непрерывную операцию «push-pop» над стеком с вызовами функций. Если вы демонстрируете что-то любителю или новичку (например, учебные материалы по C / C ++), это, вероятно, нормально. Но если вы используете такое приложение, как система наблюдения и обнаружения или система слежения за сонаром, вы не должны постоянно копировать свои объекты, потому что это рано или поздно убьет вашу программу.

person ha9u63ar    schedule 31.01.2013

char * Source = "Hello, world.";

char * ShallowCopy = Source;    

char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);        

«ShallowCopy» указывает на то же место в памяти, что и «Источник». «DeepCopy» указывает на другое место в памяти, но содержимое то же самое.

person John Dibling    schedule 08.10.2008
comment
Лучший ответ. Благодарю. - person Don Dilanga; 21.12.2020

Что такое мелкая копия?

Неглубокая копия - это побитовая копия объекта. Создается новый объект, который имеет точную копию значений в исходном объекте. Если какое-либо из полей объекта является ссылками на другие объекты, копируются только адреса ссылок, т.е. копируется только адрес памяти. Неглубокая копия

На этом рисунке MainObject1 имеет поля field1 типа int и ContainObject1 типа ContainObject. Когда вы делаете неглубокую копию MainObject1, создается MainObject2 с field2, содержащим скопированное значение field1 и по-прежнему указывающим на сам ContainObject1. Обратите внимание, что, поскольку field1 имеет примитивный тип, его значение копируется в field2, но поскольку ContainedObject1 является объектом, MainObject2 по-прежнему указывает на ContainObject1. Таким образом, любые изменения, внесенные в ContainObject1 в MainObject1, будут отражены в MainObject2.

Теперь, если это мелкая копия, давайте посмотрим, что такое глубокая копия?

Что такое Deep Copy?

Глубокая копия копирует все поля и делает копии динамически выделяемой памяти, на которую указывают поля. Глубокая копия происходит, когда объект копируется вместе с объектами, на которые он ссылается. Глубокая копия

На этом рисунке MainObject1 имеет поля field1 типа int и ContainObject1 типа ContainObject. Когда вы делаете глубокую копию MainObject1, создается MainObject2 с field2, содержащим скопированное значение field1 и ContainObject2, содержащим скопированное значение ContainObject1. Обратите внимание, что любые изменения, внесенные в ContainObject1 в MainObject1, не будут отражены в MainObject2.

хорошая статья

person atish shimpi    schedule 18.12.2014
comment
это не ваша вина, хотя этот пример относится к field3, который, когда вы в состоянии попытаться понять что-то столь же глубокое, как эта проблема, где это №3 в этом примере имеет место ContainObject2 ? - person Robb_2015; 29.12.2015

В объектно-ориентированном программировании тип включает в себя набор полей-членов. Эти поля могут храниться либо по значению, либо по ссылке (т. Е. Указатель на значение).

В мелкой копии создается новый экземпляр типа, а значения копируются в новый экземпляр. Ссылочные указатели также копируются точно так же, как и значения. Следовательно, ссылки указывают на исходные объекты. Любые изменения в элементах, которые хранятся по ссылке, появляются как в оригинале, так и в копии, поскольку копия объекта, на который имеется ссылка, не была сделана.

В глубокой копии поля, которые хранятся по значению, копируются, как и раньше, но указатели на объекты, хранящиеся по ссылке, не копируются. Вместо этого делается глубокая копия указанного объекта и сохраняется указатель на новый объект. Любые изменения, внесенные в указанные объекты, не повлияют на другие копии объекта.

person Jeffrey L Whitledge    schedule 08.10.2008

«ShallowCopy» указывает на то же место в памяти, что и «Источник». «DeepCopy» указывает на другое место в памяти, но содержимое то же самое.

person GovindaRaju    schedule 21.02.2011
comment
Это немного вводит в заблуждение. И мелкая, и глубокая копия копируют объект в новое место в памяти, глубокая копия также копирует дочерние объекты, тогда как мелкая будет просто иметь новые объекты, относящиеся к старым дочерним объектам. Трудно читать, не обращаясь к исходному объекту. - person Bill K; 05.04.2017

Неглубокое клонирование:
Определение: «Неглубокая копия объекта копирует« основной »объект, но не копирует внутренние объекты». Когда пользовательский объект (например, Employee) имеет только примитивные переменные типа String, тогда вы используете Shallow Cloning.

Employee e = new Employee(2, "john cena");
Employee e2=e.clone();

Вы возвращаете super.clone(); в переопределенном методе clone (), и ваша работа завершена.

Глубокое клонирование:
Определение: «В отличие от неглубокой копии, глубокая копия является полностью независимой копией объекта».
Означает, что объект Employee содержит другой настраиваемый объект:

Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");

Затем вам нужно написать код для клонирования объекта Address, а также в переопределенном методе clone (). В противном случае объект Address не будет клонироваться, и это вызовет ошибку при изменении значения Address в клонированном объекте Employee, который также отражает исходный.

person Arun Raaj    schedule 26.09.2017

Я хотел бы привести пример, а не формальное определение.

var originalObject = { 
    a : 1, 
    b : 2, 
    c : 3,
};

Этот код показывает неглубокую копию:

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

Этот код показывает глубокую копию:

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 !!
person Vivek Mehta    schedule 24.01.2018
comment
Я получаю 1 1 4 4 4 4 4 4 - person Suresh Prajapati; 11.08.2019
comment
в глубокой копии сделайте copyObject.a = 8, а затем проверьте. надеюсь, вы получите правильный ответ. - person Vivek Mehta; 12.08.2019
comment
object.assign ({}, arr) не будет создавать глубокую копию, предположим, что у нас есть следующий объект var source = {foo: 1, name: Testing, c: {age: 34}} var dCopy = Object.assign ({ }, источник) console.log (dCopy.c.age) console.log (Source deep ${source.c.age}) source.c.age = 3 console.log (dCopy.c.age) console.log (Source deep ${source.c.age}) - person Swarup Chavan; 29.07.2020

Глубокая копия

Глубокая копия копирует все поля и делает копии динамически выделяемой памяти, на которую указывают поля. Глубокая копия происходит, когда объект копируется вместе с объектами, на которые он ссылается.

Неглубокая копия

Неглубокая копия - это побитовая копия объекта. Создается новый объект, который имеет точную копию значений в исходном объекте. Если какое-либо из полей объекта является ссылками на другие объекты, копируются только адреса ссылок, т.е. копируется только адрес памяти.

person Sunil Kumar Sahoo    schedule 16.09.2014
comment
Эта ссылка, к сожалению, больше не работает - теперь она указывает на статью о веб-дизайне от февраля 2019 года (если автор не ясновидящий?). - person PhilPhil; 05.04.2019

Неглубокая копия - ссылочная переменная внутри исходного и неглубокого скопированных объектов ссылается на общий объект.

Глубокая копия - ссылочная переменная внутри исходного и глубоко скопированного объектов ссылается на другой объект.

clone всегда делает мелкую копию.

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

основной класс следующий-

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 из вышеперечисленного будет-

ложь правда правда

ложно ложно ложно

Любое изменение, сделанное в исходном объекте, отразится на мелком объекте, а не на глубоком.

  list.get(0).name="ViSuaLBaSiC";
  System.out.println(shallow.get(0).getName()+"  "+deep.get(0).getName());

OutPut- ViSuaLBaSiC C

person Community    schedule 07.05.2015

Проще говоря, неглубокая копия аналогична вызову по ссылке, а глубокая копия аналогична вызову по значению.

При вызове по ссылке как формальные, так и фактические параметры функции относятся к одной и той же ячейке памяти и значению.

При вызове по значению как формальные, так и фактические параметры функции относятся к разным ячейкам памяти, но имеют одинаковое значение.

person santhosh    schedule 02.12.2011

Представьте, что есть два массива с именами arr1 и arr2.

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy
person PeerNet    schedule 29.05.2015

Неглубокая копия создает новый составной объект и вставляет в него ссылки на исходный объект.

В отличие от мелкой копии, глубокая копия создает новый составной объект, а также вставляет копии исходных объектов исходного составного объекта.

Возьмем пример.

import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)

Над кодом печатается ЛОЖЬ.

Посмотрим как.

Исходный составной объект x=[1,[2]] (называется составным, потому что у него есть объект внутри объекта (Начало))

введите описание изображения здесь

как вы можете видеть на изображении, внутри списка есть список.

Затем мы создаем его неглубокую копию с помощью y = copy.copy(x). Что здесь делает python, так это то, что он создает новый составной объект, но объекты внутри него указывают на исходные объекты.

введите описание изображения здесь

На изображении он создал новую копию для внешнего списка. но внутренний список остается таким же, как и исходный.

Теперь мы создаем его глубокую копию, используя z = copy.deepcopy(x). что здесь делает python, он создаст новый объект для внешнего списка, а также для внутреннего списка. как показано на изображении ниже (выделено красным).

введите описание изображения здесь

В конце код печатает False, поскольку y и z не являются одними и теми же объектами.

HTH.

person Sushant    schedule 20.01.2018

Чтобы добавить больше к другим ответам,

  • Неглубокая копия объекта выполняет копирование по значению для свойств на основе типов значений и копирование по ссылке для свойств на основе ссылочных типов.
  • Глубокая копия объекта выполняет копирование по значению для свойств на основе типов значений, а также копирование по значению для свойств на основе ссылочных типов глубоко в иерархии (ссылочных типов)
person VSS    schedule 29.09.2016

Неглубокое копирование - это создание нового объекта, а затем копирование нестатических полей текущего объекта в новый объект. Если поле имеет тип значения -> выполняется побитовое копирование поля; для ссылочного типа -> ссылка копируется, а упомянутый объект - нет; следовательно, исходный объект и его клон относятся к одному и тому же объекту.

Глубокая копия - это создание нового объекта, а затем копирование нестатических полей текущего объекта в новый объект. Если поле имеет тип значения -> выполняется побитовое копирование поля. Если поле имеет ссылочный тип -> создается новая копия указанного объекта. Клонируемые классы должны быть помечены как [Serializable].

person Rajaram Shelar    schedule 08.08.2013

Взято из [блога]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html.

Глубокая копия предполагает использование содержимого одного объекта для создания другого экземпляра того же класса. В глубокой копии два объекта могут содержать одну и ту же информацию, но целевой объект будет иметь свои собственные буферы и ресурсы. разрушение любого объекта не повлияет на оставшийся объект. Перегруженный оператор присваивания создает глубокую копию объектов.

Неглубокая копия включает в себя копирование содержимого одного объекта в другой экземпляр того же класса, что создает зеркальное отображение. Благодаря прямому копированию ссылок и указателей два объекта будут совместно использовать одно и то же внешнее содержимое другого объекта, что будет непредсказуемо.

Объяснение:

Используя конструктор копирования, мы просто копируем значения данных член за членом. Этот метод копирования называется мелким копированием. Если объект является простым классом, состоящим из встроенных типов и без указателей, это было бы приемлемо. Эта функция будет использовать значения и объекты, и ее поведение не будет изменено мелкой копией, копируются только адреса указателей, которые являются членами, а не значение, на которое указывает адрес. Значения данных объекта тогда будут непреднамеренно изменены функцией. Когда функция выходит за пределы области видимости, копия объекта со всеми его данными извлекается из стека.

Если у объекта есть указатели, необходимо выполнить глубокую копию. При глубокой копии объекта память выделяется для объекта в свободном хранилище, и элементы, на которые указываются, копируются. Глубокая копия используется для объектов, возвращаемых функцией.

person Santosh    schedule 07.03.2014

Я пришел к пониманию из следующих строк.

Неглубокая копия копирует поля типа значения (int, float, bool) объекта в целевой объект, а ссылочные типы объекта (строка, класс и т. Д.) Копируются как ссылки в целевой объект. . В этом целевые ссылочные типы будут указывать на ячейку памяти исходного объекта.

Глубокая копия копирует значение объекта и ссылочные типы в полную новую копию целевых объектов. Это означает, что и типам значений, и ссылочным типам будут выделены новые ячейки памяти.

person Nayas Subramanian    schedule 28.07.2018

Неглубокая копия не создаст новую ссылку, но глубокая копия создаст новую ссылку.

Вот программа, объясняющая глубокую и поверхностную копию.

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 + "]";
    }
}
person Lova Chittumuri    schedule 06.03.2017

Копирование архивов:

Array - это класс, что означает, что это ссылочный тип, поэтому array1 = array2 приводит к двум переменным, которые ссылаются на один и тот же массив.

Но посмотрите на этот пример:

  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]);
    }

мелкое клонирование означает, что копируется только память, представленная клонированным массивом.

Если массив содержит объекты типа значения, значения копируются;

если массив содержит ссылочный тип, копируются только ссылки - в результате получается два массива, члены которых ссылаются на одни и те же объекты.

Чтобы создать глубокую копию, где тип ссылки дублируется, вы должны пройти через массив и клонировать каждый элемент вручную.

person komizo    schedule 19.12.2012
comment
Я не знаю о других языках, но в C # / VB неглубокое копирование массива типов значений не копирует значения. Два массива относятся к одним и тем же объектам. Добавьте кнопку в форму и добавьте этот код, чтобы увидеть: 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]); } - person DeanOC; 20.12.2012
comment
Вы правы, я исправил свой ответ, чтобы быть более точным, используя клонирование на массивах. Вы абсолютно правы в том, что неглубокое копирование массива типов значений не копирует значения, а использование клонирования в массиве копирует. Я пытался это объяснить, попробуйте. Спасибо - person komizo; 20.12.2012

В дополнение ко всем вышеперечисленным определениям еще одна и наиболее часто используемая глубокая копия находится в конструкторе копирования (или операторе перегрузки присваивания) класса.

Неглубокая копия -> - это когда вы не предоставляете конструктор копирования. Здесь копируется только объект, но не все члены класса копируются.

Глубокая копия -> - это когда вы решили реализовать конструктор копирования или присвоение перегрузки в своем классе и позволяет копировать все члены класса.

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
}
person Avinash Goud N J    schedule 20.12.2013

Конструктор копирования используется для инициализации нового объекта ранее созданным объектом того же класса. По умолчанию компилятор написал неглубокую копию. Неглубокая копия работает нормально, когда динамическое выделение памяти не задействовано, потому что, когда задействовано динамическое выделение памяти, оба объекта будут указывать на одно и то же место памяти в куче. Поэтому для устранения этой проблемы мы написали глубокую копию, чтобы у обоих объектов была собственная копия атрибутов. в памяти. Чтобы прочитать подробности с полными примерами и пояснениями, вы можете прочитать статью Конструкторы C ++ .

person royal52    schedule 08.02.2014

Чтобы добавить еще немного для путаницы между мелкой копией и просто назначить новое имя переменной для списка.

"Допустим, у нас есть:

x = [
    [1,2,3],
    [4,5,6],
    ]

Этот оператор создает 3 списка: 2 внутренних списка и один внешний список. Затем ссылка на внешний список становится доступной под именем x. Если мы сделаем

y = x

никакие данные не копируются. У нас где-то в памяти остались те же 3 списка. Все, что это сделало, - это сделало внешний список доступным под именем y в дополнение к его предыдущему имени x. Если мы сделаем

y = list(x)

or

y = x[:]

Это создает новый список с тем же содержанием, что и x. Список x содержит ссылку на 2 внутренних списка, поэтому новый список также будет содержать ссылку на те же 2 внутренних списка. Копируется только один список - внешний список. Теперь в памяти 4 списка: два внутренних списка, внешний список и копия внешнего списка. Исходный внешний список доступен под именем x, а новый внешний список доступен под именем y.

Внутренние списки не копировались! На этом этапе вы можете получить доступ к внутренним спискам и отредактировать их по x или y!

Если у вас есть двумерный (или более высокий) список или какая-либо вложенная структура данных, и вы хотите сделать полную копию всего, тогда вы хотите использовать функцию deepcopy () в модуле копирования. Ваше решение также работает для двумерных списков, поскольку выполняет итерацию по элементам внешнего списка и делает копию каждого из них, а затем создает новый внешний список для всех внутренних копий ».

источник: https://www.reddit.com/r/learnpython/comments/1afldr/why_is_copying_a_list_so_damn_difficult_in_python/

person Lance Ruo Zhang    schedule 12.01.2017

person    schedule
comment
Это плохой пример. Неглубокие копии в основном используются для быстрого копирования объектов без копирования данных, но как только объекту необходимо изменить общие данные, создается их глубокая копия. Ваш пример скорее всего запутает новичков. - person CMircea; 17.04.2010
comment
это работает только на языках, которые используют указатели для представления строк. Смысл, который пытается сделать DHA, заключается в том, что неглубокая копия дублирует только указатели на идентичный (единственный) исходный контент, в то время как глубокая копия также клонирует указанное содержимое указателей. Оба метода копируют содержимое поверхности. Если язык хранит строки как поверхностный буквальный контент, например внутри заголовка WAV этот пример работать не будет. Обратите внимание, что это, вероятно, слишком разборчиво для большинства реальных проблем, которые не являются эзотерическими. - person DragonLord; 16.11.2014