#c
#c
Вопрос:
У нас есть мелкое копирование и глубокое копирование, которые могут выполнить эту работу за нас, когда мы хотим скопировать объекты на C . Итак,
что такое отложенное копирование?
Это то, о чем заботится программист, или компилятор делает это сам по себе?
В каких сценариях программирования выгодно использовать отложенное копирование?
Комментарии:
1. Вы пробовали википедию? en.wikipedia.org/wiki/Object_copy
2. Я предполагаю, что вы погуглили и нашли это: link ?
3. Почему этот Q так часто отклоняется? По крайней мере, некоторые из Q являются допустимыми Q.
4. @phooji, Бен: «Google it» неприемлемо для SO. Либо ссылка на другой вопрос SO и пометка как дубликат, либо пометка как не по теме. Этот вопрос относится к теме терминологии.
5. Отложенное копирование более широко известно как копирование при записи или COW.
Ответ №1:
Что такое отложенное копирование?
Википедия точно определяет это.
Отложенное копирование — это комбинация как мелкого копирования, так и глубокого копирования. При первоначальном копировании объекта используется (быстрая) мелкая копия. Счетчик также используется для отслеживания того, сколько объектов совместно используют данные. Когда программа хочет изменить объект, она может определить, являются ли данные общими (путем проверки счетчика), и при необходимости может выполнить глубокое копирование. Ленивое копирование выглядит снаружи так же, как глубокое копирование, но использует преимущества скорости мелкого копирования, когда это возможно. Недостатком являются довольно высокие, но постоянные базовые затраты из-за счетчика. Кроме того, в определенных ситуациях циклические ссылки также могут вызывать проблемы.
Это то, о чем заботится программист или что-то, что компилятор делает самостоятельно?
Программист должен реализовать это поведение для своих собственных классов.
Компилятор выполняет мелкие копии в копирующих функциях (конструктор копирования и оператор присваивания) по умолчанию.
Глубокое копирование — это то, что программист должен реализовать для своего класса, чтобы специальная обработка членов (указателей) могла использоваться для копирования функций.
В каких сценариях программирования выгодно использовать отложенное копирование?
В идеале,
ситуация, когда копирование объекта приводит к снижению производительности, но объекты изменяются не очень часто, отложенное копирование было бы выгодным с точки зрения производительности.
Википедия приводит ряд примеров, в которых используется отложенное копирование (копирование при записи).
Комментарии:
1. Среди недостатков: было показано, что COW не так хорошо работает с многопоточностью (на многоядерных процессорах) из-за общего счетчика. Необходимость синхронизировать счетчик в кэше различных ядер вызывает разногласия.
Ответ №2:
Отложенное копирование примерно:
- немедленно выполните мелкое копирование
- но выполните глубокое копирование позже, только когда это станет абсолютно необходимым (т. Е. Когда Объект будет изменен), в надежде, что этот момент никогда не наступит.
Итак, это разные понятия. Отложенное копирование — это, по сути, оптимизация во время выполнения, в то время как мелкое / глубокое копирование — это конструкция времени компиляции, которая может использоваться для реализации отложенного копирования, но также может использоваться независимо.
Ответ №3:
Я не уверен, что вы подразумеваете под «наличием мелкой и глубокой копии, которая может выполнить эту работу за нас». Когда вы пишете свой конструктор копирования и оператор присваивания, вам нужно принять решение о том, как вы хотите сделать копию.
В мелком копировании вы просто копируете элементы объекта напрямую. Если эти элементы являются указателями на память кучи, копия указывает на тот же блок памяти кучи. Это копирование по умолчанию, выполняемое C , если вы не предоставляете конструктор копирования.
В глубокой копии любая память, на которую указывают указатели-члены, сама копируется (потенциально повторяется и для членов этих объектов).
В отложенном копировании вы начинаете с мелкой копии. Если объект или его дочерние элементы никогда не изменяются, тогда все в порядке. Нет необходимости создавать вторую копию памяти кучи. Когда одна из двух копий модифицируется, сначала выполняется глубокое копирование, чтобы изменения не применялись к обоим объектам. Это также известно как совместное использование при записи.
Цель отложенного копирования — создать видимость глубоких копий с некоторыми преимуществами производительности мелкого копирования. Приведет ли это к увеличению производительности, зависит от использования объектов. Если вы планируете иметь много копий объекта без изменений, то вы, вероятно, увидите преимущества. Если большинство объектов в конечном итоге все равно модифицируются, преимущества исчезают. Когда объекты изменяются очень часто, накладные расходы на проверку того, что глубокое копирование было выполнено до изменения объекта, делают его хуже, чем простое глубокое копирование.
Строки часто упоминаются как хорошие места для отложенного копирования, поскольку очень часто копии просто создаются для отображения в разных местах, но большинство строк либо все равно используют глубокие копии, либо используют мелкие копии и полностью запрещают модификацию.
Комментарии:
1. Я думаю, что вопрос OP заключается в том, зачем использовать отложенное копирование, когда уже есть два механизма мелкого и глубокого копирования.
2. копирование при записи вызывает проблемы с идентификацией в C . Схема отложенного копирования должна создавать копию при каждом обращении к подобъекту, а не только для модификации.
Ответ №4:
Отложенное копирование используется, когда вам обычно может потребоваться глубокое копирование, но вы не уверены, действительно ли это необходимо. Глубокое копирование, как правило, является дорогостоящей операцией. Если вы делаете это безоговорочно в 100% случаев, а затем обнаруживаете, что вам это нужно только в 10% объектов, то усилия, потраченные на глубокое копирование остальных 90% объектов, были потрачены впустую.
Это когда появляется отложенное копирование. Отложенное копирование — это отложенная, отложенная версия Deep Copy по требованию. С помощью ленивого копирования вы не выполняете глубокое копирование сразу. Вместо этого вы готовите (или планируете) глубокое копирование, сохраняя всю соответствующую информацию в объекте получателя (что в большинстве случаев сводится к простой мелкой копии) и ждете, пока не станет известно, действительно ли глубокое копирование необходимо для этого конкретного объекта. Если это оказывается необходимым, вы выполняете фактическое глубокое копирование. Если необходимость в глубоком копировании никогда не возникает, то этого не происходит, что экономит ваши усилия.
Ответ №5:
Позвольте мне поговорить о C
Одной из очень важных частей написания класса в C является реализация конструктора копирования и функции overloaded = operator .
В этом руководстве рассказывается о необходимости написания этих функций, чтобы сделать вашу программу более эффективной. Прежде чем перейти к концепции, давайте разберемся с базовой терминологией.
Конструктор: это специальная функция, вызываемая при создании объекта класса. В идеале конструктор должен содержать логику для инициализации элементов данных класса.
Конструктор копирования: он вызывается, когда и объект инициализируется во время создания. Существует больше сценариев, когда вызывается конструктор копирования.
Функция оператора: C позволяет перегружать operator с помощью ключевого слова operator . Это помогает нам рассматривать пользовательские типы как базовые типы.
Конструктор копирования по умолчанию и функция =operator, которая вставляется компилятором, если они отсутствуют в классе. Он выполняет копирование битового шаблона, т.Е. Просто копирует элементы данных одного объекта в другой объект.
Рассмотрим следующий пример кода
class CSample
{
int x;
public:
//dafualt constructor
CSample(): x(0){}
int GetX()
{
return x;
}
};
int main()
{
CSample ob1; //Default constructor is called.
CSample ob2 = ob1; //default copy constructor called.
CSample ob3; //Default constructor called.
ob3 = ob1; //default overloaded = operator function called.
}
В приведенном выше примере
CSample ob2 = ob1;
//This line will copy the bit pattern of ob1 in ob2 so the data member
// x in both the object will contain same value i.e 0.
Аналогично утверждение
ob3 = ob1;
//This line will copy the bit pattern of ob1 in ob2 so the data member
// x in both the object will contain same value i.e 0.
Приведенный выше код будет работать, как и ожидалось, до тех пор, пока члену класса не будет выделен какой-либо ресурс (файл или память). Рассмотрим сценарий, в котором класс обновляется следующим образом.
class CSample
{
int *x;
int N;
public:
//dafualt constructor
CSample(): x(NULL){}
void AllocateX(int N)
{
this->N = N;
x = new int[this->N];
}
int GetX()
{
return x;
}
~CSample()
{
delete []x;
}
};
int main()
{
CSample ob1; //Default constructor is called.
ob1.AllocateX(10);
//problem with this line
CSample ob2 = ob1; //default copy constructor called.
CSample ob3; //Default constructor called.
//problem with this line
ob3 = ob1; //default overloaded = operator function called.
}
class CSample
{
int *x;
int N;
public:
//dafualt constructor
CSample(): x(NULL)
{}
//copy constructor with deep copy
CSample(const CSample amp;ob)
{
this->N = ob.N:
this->x = new int[this->N];
}
//=operator function with deep copy.
void operator=(const CSample amp;ob)
{
this->N = ob.N:
this->x = new int[this->N];
}
void AllocateX(int N)
{
this->N = N;
x = new int[this->N];
}
int GetX()
{
return x;
}
~CSample()
{
delete []x;
}
};