Когда следует использовать глубокую или мелкую копию? [Дубликат]

Компилятор хочет, чтобы вы это записывали:

private static List<String> list = new ArrayList<String>();

, потому что в противном случае вы могли бы добавить любой тип, который вам нравится, в list, делая создание как new ArrayList<String>() бессмысленным. Java generics - это только функция времени компиляции, поэтому объект, созданный с помощью new ArrayList<String>(), с радостью примет Integer или JFrame элементы, если они назначены ссылке «raw type» List - сам объект ничего не знает о какие типы он должен содержать, только компилятор делает.

755
задан Dariusz Woźniak 21 February 2014 в 00:45
поделиться

30 ответов

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

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

597
ответ дан S.Lott 21 August 2018 в 14:53
поделиться

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

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

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

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

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

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

6
ответ дан Arun Raaj 21 August 2018 в 14:53
поделиться

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

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

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

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
}
0
ответ дан Avinash Goud N J 21 August 2018 в 14:53
поделиться

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

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

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

40
ответ дан Bill K 21 August 2018 в 14:53
поделиться
52
ответ дан Community 21 August 2018 в 14:53
поделиться
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
8
ответ дан Dour High Arch 21 August 2018 в 14:53
поделиться
  • 1
    Это не очень хороший пример. Мелкие копии в основном используются для быстрого копирования объектов, без копирования данных, но как только объекты должны модифицировать общие данные, выполняется глубокая копия. Ваш пример, скорее всего, путает начинающих. – CMircea 17 April 2010 в 10:05
  • 2
    это работает только на языках, которые используют указатели для представления строк. То, что DHA пытается сделать, это то, что мелкая копия только дублирует указатели на идентичное (единственное) исходное содержимое, а глубокая копия также клонирует ссылочный контент указателей. Оба метода копируют поверхностное содержимое. Если язык хранит строки как поверхностные литералы, например, внутри заголовка WAV этот пример не будет работать. Обратите внимание, что это, вероятно, слишком разборчиво для большинства реальных проблем, которые не являются эзотерическими. – DragonLord 16 November 2014 в 02:13

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

Shallow:

Before Copy [/g0] Shallow Copying [/g1] Shallow Done [/g2]

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

Глубокий:

Before Copy [/g3] Deep Copying [/g4] Deep Done [/g5]

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

715
ответ дан giannis christofakis 21 August 2018 в 14:53
поделиться
  • 1
    Вот статья из Википедии, в которой эта иллюстрация исходит из того, что она не имеет смысла из контекста для вас ru.wikipedia.org/wiki/Object_copy#Shallow_copy – corbin 7 November 2013 в 03:59
  • 2
    В случае мелкой копии, если мы сделаем какие-либо изменения в массиве B, это будет отражено в массиве A, так как A & amp; B оба указывают на то же место памяти? – tek3 16 January 2015 в 13:42
  • 3
    Таким образом, мелкая копия означает только ссылку на исходную сущность, доступную для так называемой копии. Любое изменение исходного объекта будет реплицировано на новое? Глубокая копия будет клонировать исходную сущность и создавать новую несвязанную копию. – Swanidhi 25 March 2016 в 16:22
  • 4
    изображения, непосредственно взятые из Википедии без цитаты – jasonleonhard 5 September 2017 в 05:23
  • 5
    @jasonleonhard Итак, 9 лет назад я просто размещал URL-адреса изображений, потому что встраивание изображений не поддерживалось. Таким образом, URL-адрес привел его источник. Сообщество позже превратило URL-адреса в внедренные изображения, не редактируя на нем какую-то цитату. 4-летний топ-комментарий также указывает на то, что вы указываете. Посмотрите: stackoverflow.com/posts/184780/revisions Почему бы просто не отредактировать цитату в ответ самостоятельно? Я мог бы быть недоступен в следующий раз, когда у кого-то есть жалоба на мой 10-летний стиль письма. – dlamblin 7 September 2017 в 09:08

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

13
ответ дан GovindaRaju 21 August 2018 в 14:53
поделиться
  • 1
    Это немного вводит в заблуждение. Как мелкая, так и глубокая копия скопирует объект в новое место в памяти, глубокий будет также копировать дочерние объекты, в то время как мелкие будут только новые объекты ссылаться на старых детей. Трудно читать, не обращаясь к исходному объекту. – Bill K 5 April 2017 в 17:04

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

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

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

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

EXAMPLE_OF_DEEP COPY_ Примером является то, что когда вы пытаетесь выполнить обработку изображений и распознавание объектов, вам нужно замаскировать «Irrelevant and Repeating Motion» из ваших областей обработки. Если вы используете указатели изображений, у вас может быть спецификация для сохранения этих изображений масок. СЕЙЧАС ... если вы сделаете мелкую копию изображения, когда ссылки указателя будут убиты из стека, вы потеряли ссылку и ее копию, то есть в какой-то момент будет ошибка времени выполнения. В этом случае вам нужна глубокая копия вашего изображения с помощью CLONING. Таким образом, вы можете получить маски в случае, если они вам понадобятся в будущем.

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

32
ответ дан ha9u63ar 21 August 2018 в 14:53
поделиться

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

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

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

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

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

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

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

68
ответ дан Honey 21 August 2018 в 14:53
поделиться
  • 1
    «B-адрес памяти такой же, как у A». - Как так ? – user 26 October 2015 в 10:06
  • 2
    в глубокой копии B указывает на новый адрес, отличный от A .. – miracle-doh 16 August 2017 в 15:27
  • 3
    В разделе «Глубокое копирование» адрес «B-памяти» не является таким же, как «A». – ismail baig 8 May 2018 в 04:14

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

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

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

14
ответ дан Jeffrey L Whitledge 21 August 2018 в 14:53
поделиться
char * Source = "Hello, world.";

char * ShallowCopy = Source;    

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

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

27
ответ дан John Dibling 21 August 2018 в 14:53
поделиться

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

«Скажем, у нас есть:

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

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

y = x

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

y = list(x)

или

y = x[:]

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

Внутренние списки не были пестрая!

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

source: https://www.reddit.com/r/learnpython/comments/1afldr/why_is_copying_a_list_so_damn_difficult_in_python/

0
ответ дан Lance Ruo Zhang 21 August 2018 в 14:53
поделиться

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

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 + "]";
}

}

1
ответ дан Lova Chittumuri 21 August 2018 в 14:53
поделиться

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

Массив - это класс, что означает, что он является ссылочным типом, поэтому 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]);
    }

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

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

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

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

1
ответ дан lukaszk 21 August 2018 в 14:53
поделиться
  • 1
    Я не знаю о других языках, но в C # / VB мелкое копирование массива значений типов not копирует значения. Эти два массива относятся к тем же объектам. Добавьте кнопку в форму и добавьте этот код, чтобы увидеть: 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]); } – DeanOC 19 December 2012 в 23:38
  • 2
    вы правы, я исправил свой ответ, чтобы быть более точным, используя клон на массивах. Вы абсолютно правы, что «мелкое копирование массива типов значений не копирует значения», но использование клона на массиве делает. Я попытался это объяснить, попробуйте. благодаря – lukaszk 20 December 2012 в 18:56
  • 3

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

Глубокая копия: & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; копирует значения элементов из одного объекта в другой. & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;; & nbsp; .

Пример:

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.)
55
ответ дан Martin York 21 August 2018 в 14:53
поделиться
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);
}
5
ответ дан notytony 21 August 2018 в 14:53
поделиться

Представьте, что существуют два массива, называемые arr1 и arr2.

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy
4
ответ дан PeerNet 21 August 2018 в 14:53
поделиться

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

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

1
ответ дан Rajaram Shelar 21 August 2018 в 14:53
поделиться
135
ответ дан Ray Vega 21 August 2018 в 14:53
поделиться

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

0
ответ дан royal52 21 August 2018 в 14:53
поделиться

В простых терминах «Мелкая копия» похожа на Call By Reference, а Deep Copy похожа на Call By Value

. В Call By Reference, как формальные, так и фактические параметры функции относятся к одной и той же памяти местоположение и значение.

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

5
ответ дан santhosh 21 August 2018 в 14:53
поделиться

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

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

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

Объяснение:

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

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

2
ответ дан Santosh 21 August 2018 в 14:53
поделиться

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

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

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

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

Что такое Deep Copy?

Глубокая копия копирует все поля и создает копии динамически выделенной памяти, на которые указывают поля. Глубокая копия возникает, когда объект копируется вместе с объектами, к которым он относится. Deep Copy [/g2]

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

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

18
ответ дан smci 21 August 2018 в 14:53
поделиться

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

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

Неверная копия

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

Пример копирования Deep Copy и swallow copy

3
ответ дан Sunil Kumar Sahoo 21 August 2018 в 14:53
поделиться

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

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

Давайте возьмем пример.

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

Выше кода печатает FALSE.

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

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

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

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

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

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

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

HTH.

1
ответ дан Sushant 21 August 2018 в 14:53
поделиться

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

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 !!
7
ответ дан thirtydot 21 August 2018 в 14:53
поделиться

Просто для легкого понимания вы можете следовать этой статье: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm

< hr>

Неверная копия:


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

28
ответ дан Touchstone 21 August 2018 в 14:53
поделиться

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

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

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 выше будет -

false true true

false false false

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

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

OutPut- ViSuaLBaSiC C

6
ответ дан user 21 August 2018 в 14:53
поделиться

Чтобы добавить другие ответы,

  • Мелкая копия объекта выполняет копирование по значению для свойств типов значений и копирует по ссылке для базовых свойств ссылочных типов.
  • Глубокая копия объекта выполняет копирование по значению для свойств типов значений, а также копирование по значению для базовых свойств ссылочных типов в глубину иерархии (ссылочных типов)
2
ответ дан VS1 21 August 2018 в 14:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: