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

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

+754
источник поделиться
32 ответа
  • 1
  • 2

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

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

+677
источник

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

Мелкий:

Before CopyShallow CopyingShallow Done

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

Deep:

Before CopyDeep CopyingDeep Done

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

+776
источник
другие ответы

Связанные вопросы


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

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

Эта статья wiki имеет большую диаграмму.

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

+146
источник

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

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

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

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

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

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

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

+68
источник

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

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

Например Object.MemberwiseClone создает ссылку неглубокая

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

+68
источник

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

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

Пример:

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.)
+59
источник

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

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

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

+46
источник

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


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

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


Deep Copy:

Deep Copy

+37
источник

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

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

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

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

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

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

+35
источник
char * Source = "Hello, world.";

char * ShallowCopy = Source;    

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

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

+31
источник

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

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

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

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

Что такое Deep Copy?

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

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

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

+20
источник

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

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

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

+16
источник

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

+12
источник
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
источник

Deep Copy

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

Мелкая копия

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

+8
источник

Неглубокое клонирование:
Определение: "Неглубокая копия объекта копирует" основной объект ", но не копирует внутренние объекты". Когда пользовательский объект (например, 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, который также отражает исходный.

+8
источник

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

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

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

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

+7
источник

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

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
источник
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
источник

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

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

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

+5
источник

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

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy
+5
источник

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

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

+2
источник

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

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

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

Объяснение:

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

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

+2
источник

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

  • Мелкая копия объекта выполняет копирование по значению для типов значений основанные на свойствах, и копировать по ссылке для свойств ссылочных типов.
  • Глубокая копия объекта выполняет копирование по значению для типов значений на основе свойства, а также копировать по значению для ссылочных типов на основе свойства в глубине иерархии (ссылочных типов)
+2
источник

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

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

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 + "]";
    }
}
+2
источник

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

НТН.

+2
источник

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

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

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

  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
источник

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

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

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
источник

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

0
источник

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

Неглубокая копия объекта - это новый объект, переменные экземпляра которого идентичны старому объекту. В .Net неглубокая копия выполняется объектным методом MemberwiseClone().

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

Подробнее о...... глубокая копия и мелкая копия

Rj

0
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос