2010-07-28 6 views
8

Может ли кто-нибудь привести пример ситуации, когда требуется мелкая копия?Когда требуется мелкая копия (вместо глубокой копии)?

Обратите внимание, что в некоторых ситуациях мелкая копия и глубокая копия одинаковы. Это может произойти, когда объект не имеет права владения над любой из его подвариант; то есть все подварианты: aggregated. Я хотел бы видеть примеры, когда объект имеет composed из переменных, которыми он владеет, и все же желательно скопировать их неглубоко.

Примечание: Мне не важно, на каких языках приводятся примеры. Я задаю этот вопрос с точки зрения C++/Java/C#, хотя я думаю, что копирование является языковой агностикой.

ответ

4

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

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

+0

это отличный пример! Спасибо. –

+0

Кстати, вы когда-нибудь сталкивались с ситуацией, когда это было невозможно или нежелательно копировать не принадлежащие данные, и, таким образом, сериализацию оборванного указателя? –

+0

внешних ресурсов (например, соединения с базой данных) являются «не скопируемыми». Но это не значит, что вам нужно хранить обвисший указатель, вы можете подготовиться к нему, освободив ресурс до сериализации. –

2

Как я уже указывал в своем ответе на ваш родственный вопрос, многие языки действительно не имеют понятия мелкой и глубокой копии. Тем не менее, этот класс в C++, который мешает вам использовать указатель NULL может быть пример, где требуется «мелкой» Копия:

template <typename T> 
struct NotNull { 

    T * p; 

    NotNull(T * t) : p(t) {} 

    T & operator *() { 
     if (! p) { 
      throw "null!"; 
     } 
     return * p; 
    } 
}; 

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

4

Исходя из C++ POV, был бы один сценарий, что я буду использовать мелкую копию: при реализации механизма копирования на запись.

+0

Да, ленивое копирование - еще один хороший пример, спасибо! Хотя концептуально, это все равно глубокая копия, конечно: p –

8

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

+0

Действительно! Хотя это особый случай ленивого копирования, поэтому я делаю то же замечание, что и для YeenFei: концептуально он по-прежнему является глубокой копией. –

2

Я считаю, что ситуации, когда вы используете глубокую копию, различны для C++ и Java.

  • В C++, вы можете использовать глубокое копирование, чтобы избежать сложных проблем управления памятью, или сделать его проще реализовать многопоточное приложение с.

  • В Java, глубокое копирование не требуется по этим причинам. Поскольку языки собираются вместе с мусором, нет необходимости проходить через обручи в свободные структуры данных. Поэтому для упрощения проблемы не требуется глубокая копия. Аналогично, Java имеет встроенную поддержку для синхронизации доступа несколькими потоками к общим структурам данных.

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

3
class Element{ 
} 

class Example { 
    private List<Element> elementList = new ArrayList<Element(); 

    public List<Element> getElementList() { 
     return new ArrayList<Element>(this.elementList); 
    } 

    public void addElement(Element e) { 
     elementList.add(e); 
    } 

    public void removeElement(Element e) { 
     elementList.remove(e); 
    } 
} 

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

3

Если вы посмотрите на шаблоны дизайна Gang of Four, вы увидите узор под названием FlyWeight.Вот цитата из Википедии:

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

Это было бы приемлемым использованием мелкой копии.

1

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

1

Примечание: Мне не важно, на каких языках приводятся примеры. Я задаю этот вопрос с точки зрения C++/Java/C#, хотя я думаю, что копирование является языковой агностикой.

Я думаю, что это немного зависит от языка.

В C++ копирование играет совсем другую роль, чем в Java/C#. В C++ я не могу придумать много случаев, когда мелкое копирование имеет смысл. Вместо этого вы обычно просто создаете ссылки или указатели на объект. Конструкторы копирования обычно выполняют глубокие копии, потому что на C++ объект берет на себя ответственность за своих членов и отвечает за управление их жизнью. Поскольку нет GC, эти семантики владения становятся важными, и вы не можете просто иметь два объекта, указывающих на третье, без особого внимания (они используют подсчет ссылок, чтобы сохранить третьего живым? Если нет, то какой из двух объектов владеет это?)

Я бы даже сказал, что различие между «глубокими» и «неглубокими» копиями на самом деле не имеет смысла в C++. Копия создает все, что необходимо для работы вновь созданного объекта. Иногда он разделяет бит данных (обычно это данные, которые не принадлежат ни одному из объектов), поэтому он может быть не «истинной» глубокой копией », но он также не является мелким, поскольку основная часть класса обычно это копируется.

+0

Интересное замечание. Вы совершенно правы, что C++ в значительной степени полагается на глубокое копирование, и эта собственность важнее, чем на C# или Java. Тем не менее, глубокое копирование актуально и для C#, и для Java, хотя это необходимо гораздо реже. Я думаю, что на самом деле в C# или Java более соблазнительно реализовать мелкую копию, но я подозреваю, что это потому, что реализация глубокой копии более назойливая, и в большинстве случаев мелкая копия будет достаточно случайной. –

Смежные вопросы