Мені цікаво, які можливі достоїнства має копіювання при написанні? Звичайно, я не чекаю особистої думки, але реальні практичні сценарії, де це може бути технічно і практично корисно в відчутному плані. І під відчутним я маю на увазі щось більше, ніж врятувати вас набравши &
персонажа.
Для уточнення це питання знаходиться в контексті типів даних, де присвоєння або побудова копії створює неявну дрібну копію, але модифікації до неї створюють неявну глибоку копію і застосовують зміни до неї замість оригінального об'єкта.
Причину, про яку я питаю, - я, здається, не знаходжу жодних достоїнств того, що COW є неявною поведінкою за замовчуванням. Я використовую Qt, для якого COW реалізований для багатьох типів даних, практично для всіх, що мають деякі основні динамічно розподілені сховища. Але як це справді приносить користь користувачеві?
Приклад:
QString s("some text");
QString s1 = s; // now both s and s1 internally use the same resource
qDebug() << s1; // const operation, nothing changes
s1[o] = z; // s1 "detaches" from s, allocates new storage and modifies first character
// s is still "some text"
Що ми виграємо, використовуючи COW у цьому прикладі?
Якщо все, що ми маємо намір - це використовувати const-операції, s1
це зайве, можливо, також використовувати s
.
Якщо ми маємо намір змінити значення, то COW затримує лише копію ресурсу до першої операції, що не вимагає const, за (хоча і мінімальною) вартістю збільшення кількості посилань для неявного спільного використання та від'єднання від спільного сховища. Це виглядає так, що всі накладні витрати на КРС безглузді.
Це не сильно відрізняється в контексті передачі параметрів - якщо ви не збираєтесь змінювати значення, передайте як посилання const, якщо ви хочете змінити, ви або зробите неявну глибоку копію, якщо не хочете змінювати оригінальний об'єкт або перейдіть за посиланням, якщо ви хочете його змінити. Знову COW здається непотрібним накладними, що нічого не досягає, і лише додає обмеження, що ви не можете змінювати початкове значення, навіть якщо хочете, оскільки будь-яка зміна відмежуватиметься від початкового об'єкта.
Тож залежно від того, чи знаєте ви про КОР або не звертаєте на це уваги, це може призвести або до коду з неясним наміром і непотрібним накладним навантаженням, або зовсім заплутаною поведінкою, яка не відповідає очікуванням, і залишає вас дряпати голову.
Мені здається, що є більш ефективні і читабельні рішення, чи потрібно уникати зайвої глибокої копії, чи ви збираєтесь її зробити. Тож де практична користь від корова? Я припускаю, що має бути якась користь, оскільки вона використовується в таких популярних і потужних рамках.
Крім того, з того, що я читав, COW зараз явно заборонено в стандартній бібліотеці C ++. Не знаю, чи є бачимо, що я бачу в ньому, щось спільне з цим, але в будь-якому випадку, в цьому повинна бути причина.
[]
оператора. Тож COW забезпечує поганий дизайн - це не здається великою користю :) Точка в останньому абзаці видається дійсною, але я сам не є великим прихильником неявної поведінки - люди, як правило, сприймають це як належне, а потім мають важко розібратися, чому код не працює, як очікувалося, і продовжувати цікавитись, поки вони не з’ясують, щоб перевірити, що ховається за неявною поведінкою.