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




shallow copy перевод (20)

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

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


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

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


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

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

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


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

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

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

Объяснение:

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

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


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


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

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

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

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

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

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


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

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

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

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

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

Пример:

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.)

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

В отличие от мелкой копии, 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 не являются одними и теми же объектами.

НТН.


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

Например, Object.MemberwiseClone создает link с мелкой копией

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



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

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

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

Мелкий:

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

Deep:

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


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

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

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


Deep Copy

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

Мелкая копия

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

Пример с глубокой копией и мелкой копией


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

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

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

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


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

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


Особенно для разработчиков iOS:

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

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

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

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

B совпадает с адресом A

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


char * Source = "Hello, world.";

char * ShallowCopy = Source;    

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

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


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




shallow-copy