В чем разница между глубокой и мелкой копиями?
language-agnostic
copy
deep-copy
shallow-copy
Дэвид Лок
источник
источник
Ответы:
Мелкие копии дублируют как можно меньше. Мелкая копия коллекции - это копия структуры коллекции, а не ее элементы. С мелкой копией две коллекции теперь совместно используют отдельные элементы.
Глубокие копии дублируют все. Глубокая копия коллекции - это две коллекции со всеми дублированными элементами оригинальной коллекции.
источник
Ширина против Глубины; мыслить в терминах дерева ссылок с вашим объектом в качестве корневого узла.
Мелкий:
Переменные A и B относятся к разным областям памяти, когда B присваивается A, две переменные относятся к одной и той же области памяти. Более поздние модификации содержимого любого из них немедленно отражаются в содержимом другого, поскольку они разделяют содержимое.
Deep:
Переменные A и B относятся к различным областям памяти, когда B присваивается A значения в области памяти, на которые указывает A, копируются в область памяти, на которую указывает B. Более поздние модификации содержимого либо остаются уникальными для A или B; содержание не передается.
источник
Короче, это зависит от того, что указывает на что. В мелкой копии объект B указывает на местоположение объекта A в памяти. При глубоком копировании все вещи в ячейке памяти объекта A копируются в ячейку памяти объекта B.
Эта вики статья имеет отличную схему.
http://en.wikipedia.org/wiki/Object_copy
источник
Попробуйте рассмотреть следующее изображение
Например, Object.MemberwiseClone создает ссылку для мелкого копирования
и используя интерфейс ICloneable, вы можете получить глубокое копирование, как описано здесь
источник
Специально для разработчиков iOS:
Если
B
это мелкая копия изA
, то для примитивных данных это , какB = [A assign];
и для объектов , это какB = [A retain]
;B и A указывают на одну и ту же ячейку памяти
Если
B
это глубокая копия изA
, то это какB = [A copy];
B и A указывают на разные области памяти
Адрес памяти B такой же, как и у A
Б имеет то же содержание, что и А
источник
Мелкая копия: копирует значения элементов из одного объекта в другой.
Deep Copy: копирует значения элементов из одного объекта в другой.
Любые объекты указателя дублируются и копируются.
Пример:
источник
Я не видел короткого, легкого для понимания ответа здесь - поэтому я попробую.
При неглубоком копировании любой объект, на который указывает источник, также указывается адресатом (так что ссылочные объекты не копируются).
При глубокой копии любой объект, на который указывает источник, копируется, а на копию указывает пункт назначения (так что теперь будет 2 из каждого ссылочного объекта). Это повторяется в дереве объектов.
источник
Просто для простоты понимания вы можете следить за этой статьей: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
Мелкая копия:
Глубокая копия:
источник
{Представьте себе два объекта: A и B одного и того же типа _t (по отношению к C ++), и вы думаете о мелком / глубоком копировании A в B}
Shallow Copy: просто делает копию ссылки на A в B. Думайте об этом как о копии адреса A. Таким образом, адреса A и B будут одинаковыми, то есть они будут указывать на одну и ту же ячейку памяти, то есть содержимое данных.
Глубокая копия: просто делает копию всех членов A, выделяет память в другом месте для B и затем назначает скопированные элементы B для достижения глубокой копии. Таким образом, если A становится несуществующим, B все еще действует в памяти. Правильным термином для использования будет клонирование, когда вы знаете, что оба они абсолютно одинаковы, но все же различны (т.е. хранятся как два разных объекта в пространстве памяти). Вы также можете предоставить свою обертку для клонов, где вы можете решить, используя список включения / исключения, какие свойства выбрать при глубоком копировании. Это довольно распространенная практика при создании API.
Вы можете сделать мелкую копию ONLY_IF, если вы понимаете, какие ставки включены . Когда у вас есть огромное количество указателей для работы в C ++ или C, создание мелкой копии объекта действительно ДЕЙСТВИТЕЛЬНО плохая идея.
EXAMPLE_OF_DEEP COPY_ Например, когда вы пытаетесь выполнить обработку изображений и распознавание объектов, вам необходимо скрыть «неактуальное и повторяющееся движение» из областей обработки. Если вы используете указатели изображений, то у вас может быть спецификация для сохранения этих изображений маски. СЕЙЧАС ... если вы делаете поверхностную копию изображения, когда ссылки указателя УБИВАЮТСЯ из стека, вы теряете ссылку и ее копию, то есть в какой-то момент произойдет ошибка нарушения доступа. В этом случае вам понадобится глубокая копия вашего изображения путем клонирования. Таким образом, вы можете получить маски на случай, если они понадобятся вам в будущем.
EXAMPLE_OF_SHALLOW_COPY Я не очень хорошо осведомлен по сравнению с пользователями в StackOverflow, поэтому не стесняйтесь удалять эту часть и приводите хороший пример, если можете уточнить. Но я действительно думаю, что не стоит делать поверхностное копирование, если вы знаете, что ваша программа будет работать в течение бесконечного периода времени, то есть непрерывной операции push-pop над стеком с вызовами функций. Если вы демонстрируете что-то любителю или начинающему человеку (например, учебные материалы по C / C ++), то это, вероятно, хорошо. Но если вы используете приложение, такое как система наблюдения и обнаружения, или Sonar Tracking System, вы не должны продолжать поверхностно копировать ваши объекты, потому что это рано или поздно убьет вашу программу.
источник
«ShallowCopy» указывает на то же место в памяти, что и «Source». «DeepCopy» указывает на другое место в памяти, но его содержимое одинаково.
источник
Что такое мелкая копия?
Мелкая копия - побитовая копия объекта. Создается новый объект, который имеет точную копию значений в исходном объекте. Если какие-либо поля объекта являются ссылками на другие объекты, копируются только ссылочные адреса, т. Е. Копируется только адрес памяти.
На этом рисунке
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
.хорошая статья
источник
field3
который, когда в состоянии попытаться понять что-то настолько глубокое, как эта проблема, где же находится этот № 3 в этом примереContainObject2
?В объектно-ориентированном программировании тип включает в себя коллекцию полей-членов. Эти поля могут храниться либо по значению, либо по ссылке (т. Е. Указатель на значение).
В мелкой копии создается новый экземпляр типа, а значения копируются в новый экземпляр. Ссылочные указатели также копируются как значения. Поэтому ссылки указывают на исходные объекты. Любые изменения в элементах, которые хранятся по ссылке, отображаются как в оригинале, так и в копии, поскольку не было сделано ни одной копии ссылочного объекта.
При глубоком копировании поля, которые хранятся по значению, копируются, как и раньше, но указатели на объекты, сохраненные по ссылке, не копируются. Вместо этого делается глубокая копия ссылочного объекта, и указатель на новый объект сохраняется. Любые изменения, внесенные в эти объекты, на которые есть ссылки, не влияют на другие копии объекта.
источник
«ShallowCopy» указывает на то же место в памяти, что и «Source». «DeepCopy» указывает на другое место в памяти, но его содержимое одинаково.
источник
Неглубокое клонирование:
определение: «Неглубокая копия объекта копирует« основной »объект, но не копирует внутренние объекты». Когда пользовательский объект (например, Employee) имеет только примитивные переменные типа String, тогда вы используете Shallow Cloning.
Вы возвращаетесь
super.clone();
в переопределенном методе clone (), и ваша работа закончена.Глубокое клонирование :
определение: «В отличие от мелкой копии, глубокая копия является полностью независимой копией объекта».
Означает, что объект Employee содержит другой пользовательский объект:
Затем вы должны написать код для клонирования объекта Address также в переопределенном методе clone (). В противном случае объект Address не будет клонирован, и это приведет к ошибке при изменении значения Address в клонированном объекте Employee, который также отражает исходный объект.
источник
источник
Deep Copy
Глубокая копия копирует все поля и создает копии динамически распределенной памяти, на которую указывают поля. Глубокое копирование происходит, когда объект копируется вместе с объектами, на которые он ссылается.
Мелкая копия
Мелкая копия - побитовая копия объекта. Создается новый объект, который имеет точную копию значений в исходном объекте. Если какие-либо поля объекта являются ссылками на другие объекты, копируются только ссылочные адреса, т. Е. Копируется только адрес памяти.
источник
Shallow Copy - Ссылочная переменная внутри оригинальных и мелко скопированных объектов имеет ссылку на общий объект.
Deep Copy - Ссылочная переменная внутри оригинальных и глубоко скопированных объектов имеет ссылку на другой объект.
основной класс следующий-
OutPut выше будет
Любое изменение, сделанное в оригинальном объекте, отразится на мелком объекте, а не на глубоком объекте.
OutPut- ViSuaLBaSiC C
источник
Я хотел бы привести пример, а не формальное определение.
Этот код показывает мелкую копию :
Этот код показывает глубокую копию :
источник
1 1 4 4 4 4 4 4
источник
Проще говоря, мелкая копия похожа на вызов по ссылке, а глубокая копия похожа на вызов по значению
В вызове по ссылке как формальные, так и фактические параметры функции относятся к одной и той же ячейке памяти и значению.
В вызове по значению формальные и фактические параметры функции относятся к разным ячейкам памяти, но имеют одно и то же значение.
источник
Представьте, что есть два массива с именами arr1 и arr2.
источник
Мелкая копия создает новый составной объект и вставляет в него ссылки на исходный объект.
В отличие от мелкого копирования, deepcopy создает новый составной объект, а также вставляет копии исходных объектов исходного составного объекта.
Давайте возьмем пример.
Над кодом печатается ЛОЖЬ.
Давай посмотрим как.
Исходный составной объект
x=[1,[2]]
(называется составным, потому что у него есть объект внутри объекта (Inception))как вы можете видеть на картинке, внутри списка есть список.
Затем мы создаем поверхностную копию, используя
y = copy.copy(x)
. Здесь Python создает новый составной объект, но объекты внутри него указывают на оригинальные объекты.В изображении он создал новую копию для внешнего списка. но внутренний список остается таким же, как и исходный.
Теперь мы создаем его глубокую копию
z = copy.deepcopy(x)
. Что Python делает здесь, так это то, что он создаст новый объект для внешнего списка, а также для внутреннего списка. как показано на рисунке ниже (выделено красным).В конце кода печатается
False
, так как y и z не являются одинаковыми объектами.НТН.
источник
При поверхностном копировании создается новый объект, а затем копируются нестатические поля текущего объекта в новый объект. Если поле является типом значения -> выполняется побитовая копия поля; для ссылочного типа -> ссылка копируется, а ссылочный объект - нет; поэтому исходный объект и его клон ссылаются на один и тот же объект.
Глубокая копия создает новый объект, а затем копирует нестатические поля текущего объекта в новый объект. Если поле является типом значения -> выполняется побитовая копия поля. Если поле является ссылочным типом -> выполняется новая копия упомянутого объекта. Клонируемые классы должны быть помечены как [Сериализуемые].
источник
Взято из [блога]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Глубокое копирование включает использование содержимого одного объекта для создания другого экземпляра того же класса. В глубокой копии два объекта могут содержать одну и ту же информацию, но целевой объект будет иметь свои собственные буферы и ресурсы. уничтожение любого объекта не повлияет на оставшийся объект. Перегруженный оператор присваивания создаст глубокую копию объектов.
Мелкое копирование включает в себя копирование содержимого одного объекта в другой экземпляр того же класса, создавая таким образом зеркальное отображение. Благодаря прямому копированию ссылок и указателей эти два объекта будут совместно использовать одно и то же внешнее содержимое другого объекта, что будет непредсказуемым.
Объяснение:
Используя конструктор копирования, мы просто копируем значения данных по элементам. Этот метод копирования называется мелким копированием. Если объект является простым классом, состоящим из встроенных типов и без указателей, это будет приемлемо. Эта функция будет использовать значения и объекты, и ее поведение не будет изменено с мелкой копией, копируются только адреса указателей, являющихся членами, а не значение, на которое указывает адрес. Значения данных объекта затем будут случайно изменены функцией. Когда функция выходит из области видимости, копия объекта со всеми его данными извлекается из стека.
Если объект имеет какие-либо указатели, необходимо выполнить глубокое копирование. При глубоком копировании объекта память выделяется для объекта в свободном хранилище, а указанные элементы копируются. Глубокая копия используется для объектов, которые возвращаются из функции.
источник
Чтобы добавить больше к другим ответам,
источник
Мелкая копия не создаст новую ссылку, но глубокая копия создаст новую ссылку.
Вот программа для объяснения глубокой и мелкой копии.
источник
Копирование статей:
Массив является классом, что означает, что это ссылочный тип, поэтому array1 = array2 приводит к двум переменным, которые ссылаются на один и тот же массив.
Но посмотрите на этот пример:
мелкий клон означает, что копируется только память, представленная клонированным массивом.
Если массив содержит объекты типа значения, значения копируются ;
если массив содержит ссылочный тип, копируются только ссылки, поэтому в результате появляются два массива, члены которых ссылаются на одни и те же объекты .
Чтобы создать глубокую копию - там, где ссылочный тип дублируется, вы должны пройти через массив и клонировать каждый элемент вручную.
источник
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]); }
Я пришел к пониманию из следующих строк.
При мелком копировании поля типа значения объекта (int, float, bool) копируются в целевой объект, а ссылочные типы объекта (строка, класс и т. Д.) Копируются как ссылки в целевой объект. В этой цели ссылочные типы будут указывать на место в памяти исходного объекта.
Глубокая копия копирует значение объекта и ссылочные типы в полную новую копию целевых объектов. Это означает, что как типам значений, так и ссылочным типам будут выделены новые ячейки памяти.
источник
Помимо всех приведенных выше определений, еще один и наиболее часто используемый глубокий экземпляр находится в конструкторе копирования (или перегружающем операторе присваивания) класса.
Мелкая копия -> это когда вы не предоставляете конструктор копирования. Здесь копируется только объект, но копируются не все члены класса.
Глубокое копирование -> это когда вы решили реализовать конструктор копирования или присвоение перегрузки в своем классе и разрешить копирование всех членов класса.
источник
Конструктор копирования используется для инициализации нового объекта ранее созданным объектом того же класса. По умолчанию компилятор написал поверхностную копию. Мелкое копирование работает хорошо, когда динамическое выделение памяти не задействовано, потому что, когда задействовано динамическое выделение памяти, оба объекта будут указывать на одну и ту же область памяти в куче. Поэтому, чтобы устранить эту проблему, мы написали глубокое копирование, чтобы оба объекта имели свою собственную копию атрибутов. в памяти. Для того, чтобы прочитать подробности с полными примерами и пояснениями, вы можете увидеть в статье конструкторы C ++ .
источник