powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Идиома copy-on-swap С++
25 сообщений из 39, страница 1 из 2
Идиома copy-on-swap С++
    #38877483
Фотография Станислав Клевцов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.

Есть описание идиомы на WIKIPEDIA
https://ru.wikipedia.org/wiki/Идиома_copy-and-swap

Кто - нибудь может объяснить тоже самое, но только в двух словах и более простом языком ?
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877507
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Станислав Клевцов,

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

2) Решение.
Сначала создать временный объект, копию того из которого присваивается.
Если на этом этапе произойдет исключение, то текущий объект пока еще не изменен и несогласованности нет.
Потом производится обмен полей временного объекта с полями конечного объекта путем простого побайтового копирования. Такое копирование не может выбросить исключение и оно почти не вносит дополнительных расходов.
На завершающем этапе присвоения вызовется деструктор временного объекта и очистит поля ранее принадлежавшие конечному объекту.

Таким образом данное решение позволяет всегда иметь объекты в согласованном состоянии.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877509
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Иными словами проблема высосана из пальца. И ее решение хоть и достаточно элегантно, но не имеет смысла.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877514
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlИными словами проблема высосана из пальца
Это вполне реальная проблема.
Конечно с точки зрения С-шника, необходимость вручную убирать выделенную память не является проблемой.
Но в С++ концепция другая - главная цель создания С++ - переложить всю ручную работу на компилятор.
Данная идиома показывает как это сделать проще всего для конкретной задачи.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877515
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite OwlИными словами проблема высосана из пальца
Это вполне реальная проблема.
Конечно с точки зрения С-шника, необходимость вручную убирать выделенную память не является проблемой.
Но в С++ концепция другая - главная цель создания С++ - переложить всю ручную работу на компилятор.
Данная идиома показывает как это сделать проще всего для конкретной задачи.Вот я так и чувствовал что на мой фундамент начнут кивать...

Подразумевается что есть класс:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
class A {
   string *str1, *str2;
   A() {
      str1 = new string();
      str2 = new string();
   }

   A& operator=(const A & a) {
     str1 = new string(a.str1);  // can fail
     str2 = new string(a.str2);  // can fail
     return *this;
  }

  ~A() {
     delete str1;
     delete str2;
  }

  void set_data( ... ) {....} // do something
};



A a, b;
a.set_data ( );

try {
   b=a;
} catch (Exception e) {
   delete b;
}


И теперь, если одно из присвоений внутри operator=() упало, то в последней строке состояние b будет неопределенным. Было заполнено str1? str2? или еще что-то упало? В каком объеме надо очищать b?
Я правильно понимаю вашу проблему?
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877516
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlИ теперь, если одно из присвоений внутри operator=() упало, то в последней строке состояние b будет неопределенным. Было заполнено str1? str2? или еще что-то упало? В каком объеме надо очищать b?
Я правильно понимаю вашу проблему?
Да, обычно новички каждый раз заново придумывают как реализовать оператор =.
И чаще всего, как и в вашем случае, он неверно реализован.
Например, не удаляется предыдущее значение полей.
И прочее.
Чтобы не придумывать каждый раз, данная идиома показывает как тривиально реализовать =, который автоматически не имеет указанных проблем и заодно не требует перехвата исключений.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877520
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite OwlИ теперь, если одно из присвоений внутри operator=() упало, то в последней строке состояние b будет неопределенным. Было заполнено str1? str2? или еще что-то упало? В каком объеме надо очищать b?
Я правильно понимаю вашу проблему?
Да, обычно новички каждый раз заново придумывают как реализовать оператор =.
И чаще всего, как и в вашем случае, он неверно реализован.
Например, не удаляется предыдущее значение полей.
И прочее.
Чтобы не придумывать каждый раз, данная идиома показывает как тривиально реализовать =, который автоматически не имеет указанных проблем и заодно не требует перехвата исключений.Не требует? Точно?
То есть ты утверждаешь что если оператор присваивания переписать через copy-and-swap, то исключения возникнуть не смогут?
А исключения которые могут возникнуть внутри конструктора копирования (и по тем-же самым причинам) ты в расчет не принимаешь?
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877521
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlТо есть ты утверждаешь что если оператор присваивания переписать через copy-and-swap, то исключения возникнуть не смогут?
Могут.
White OwlА исключения которые могут возникнуть внутри конструктора копирования (и по тем-же самым причинам) ты в расчет не принимаешь?
Да, не принимаю, т.к. это забота конструктора копирования (который по-любому нужно реализовать если требуется оператор=), и к тому же в правильно написанном конструкторе компилятор сам заботится о исключениях.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877525
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite OwlТо есть ты утверждаешь что если оператор присваивания переписать через copy-and-swap, то исключения возникнуть не смогут?
Могут.Я рад что ты это понимаешь.

Anatoly MoskovskyWhite OwlА исключения которые могут возникнуть внутри конструктора копирования (и по тем-же самым причинам) ты в расчет не принимаешь?
Да, не принимаю, т.к. это забота конструктора копирования (который по-любому нужно реализовать если требуется оператор=), А вот это очень даже плохо. На этом вы, любимые мои сипипифилы, и горите.

Во первых, никто не гарантирует что конструктор копирования написан правильно (а не точно так как я показал в примере кривого оператора присваивания).
Во вторых, для copy-and-swap надо еще написать правильный метод swap. Что тоже не всегда тривиально.
В третьих, даже если конструктор копирования и swap() написаны правильно - конструктор все равно может упасть. И значит каждый a=b; надо оборачивать в try{}catch (или ловить исключение выше по стеку).
Это были минусы copy-and-swap. В плюсах:
- при наличии обоих методов: конструктора копирования и оператора присваивания, если один метод вызывает другой то жить чуть проще становится. Что однако нивелируется необходимостью написания метода swap()...
- если a=b все-же упала, то мы точно знаем что a это "пустой" объект.

Однако! Если правильно написать operator=() то и проблемы несогласованного состояния тоже никогда не будет. А если неправильно написать конструктор копирования, то проблема несогласованного состояния все равно возникнет.


Вывод: используешь ты этот патерн или нет разницы никакой нет. Без него тебе надо продуманно писать operator=() и конструктор копирования. С ним тебе надо продуманно писать конструктор копирования и swap(). Работы в итоге получается практически одинаково. Упасть на a=b можно в обоих случаях и с одинаковым результатом.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877527
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlВо первых, никто не гарантирует что конструктор копирования написан правильно (а не точно так как я показал в примере кривого оператора присваивания).
Написать конструктор правильно намного проще, чем присвоение.

White OwlВо вторых, для copy-and-swap надо еще написать правильный метод swap. Что тоже не всегда тривиально.
Нет. Всегда тривиально.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
friend void swap(T& a, T& b)
{
	using std::swap;
	swap(a.f1, b.f1);
	swap(a.f2, b.f2);
	swap(a.f3, b.f3);
}


Если это нетривиально, то что тогда тривиально ))
White OwlВ третьих, даже если конструктор копирования и swap() написаны правильно - конструктор все равно может упасть. И значит каждый a=b; надо оборачивать в try{}catch (или ловить исключение выше по стеку).
Нет. Не надо оборачивать ничего. Исключения ловятся там где это задумано по дизайну приложения, а не в операторе присвоения из-за неумения написать его правильно - это и есть цель которая достигается данной идиомой

White OwlВывод: используешь ты этот патерн или нет разницы никакой нет. Без него тебе надо продуманно писать operator=() и конструктор копирования. С ним тебе надо продуманно писать конструктор копирования и swap(). Работы в итоге получается практически одинаково. Упасть на a=b можно в обоих случаях и с одинаковым результатом.
Садитесь два. Изучайте заново материал ))

ЗЫ. White Owl, критика всегда уместна. Критиковать можно даже то, в чем не разбираешься. Но не надо облекать это в форму советов бывалого и тем более заниматься дартаньянизмом :)
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877549
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite OwlВо первых, никто не гарантирует что конструктор копирования написан правильно (а не точно так как я показал в примере кривого оператора присваивания).
Написать конструктор правильно намного проще, чем присвоение.Почему? В чем разница?

Anatoly MoskovskyWhite OwlВо вторых, для copy-and-swap надо еще написать правильный метод swap. Что тоже не всегда тривиально.
Нет. Всегда тривиально.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
friend void swap(T& a, T& b)
{
	using std::swap;
	swap(a.f1, b.f1);
	swap(a.f2, b.f2);
	swap(a.f3, b.f3);
}


Если это нетривиально, то что тогда тривиально ))Тривиально это отсутствие метода. А в данном случае нетривиально то, что надо не забыть перечислить все поля. И это только в минимуме, если используемые ресурсы это исключительно куски памяти. А если копируемые ресурсы что-то более сложное (ну хоть хендлы на файлы или мютексы) то простым std::swap уже не отделаешься.

Anatoly MoskovskyWhite OwlВ третьих, даже если конструктор копирования и swap() написаны правильно - конструктор все равно может упасть. И значит каждый a=b; надо оборачивать в try{}catch (или ловить исключение выше по стеку).
Нет. Не надо оборачивать ничего. Исключения ловятся там где это задумано по дизайну приложения, а не в операторе присвоения из-за неумения написать его правильно - это и есть цель которая достигается данной идиомойХорошо. Вот в этом посте 17253298 , я показал не правильный код. Покажи мне правильный код пожалуйста.
Приведи правильный код класса который никогда не сможет упасть на присвоении.

Anatoly MoskovskyЗЫ. White Owl, критика всегда уместна. Критиковать можно даже то, в чем не разбираешься. Но не надо облекать это в форму советов бывалого и тем более заниматься дартаньянизмом :)Cura te ipsum
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877802
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlAnatoly MoskovskyНаписать конструктор правильно намного проще, чем присвоение.Почему? В чем разница?
1) в конструкторе не надо очищать старые значения (что уже проще)
2) при исключении в конструкторе, автоматически вызываются деструкторы тех полей, которые инициализированы на момент исключения (что намного проще, чем руками откатывать значения в =)

White OwlТривиально это отсутствие метода. А в данном случае нетривиально то, что надо не забыть перечислить все поля. И это только в минимуме, если используемые ресурсы это исключительно куски памяти. А если копируемые ресурсы что-то более сложное (ну хоть хендлы на файлы или мютексы) то простым std::swap уже не отделаешься.
Если swap не работает на одном из полей, то в такой объект вообще нельзя присваивать.
Хотя в частности ваш пример с хендлами такого ограничения не имеет - ничего не мешает делать хендлу swap.
White OwlПриведи правильный код класса который никогда не сможет упасть на присвоении.
Господи, ну нет такой задачи не упасть. Задача - при исключении оставить объект в согласованном состоянии, чтобы после перехвата исключения где-то там наверху можно было продолжить работу с объектом.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877809
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlА в данном случае нетривиально то, что надо не забыть перечислить все поля.
А также не забыть включить компьютер, сохранить файл перед компиляцией, и другие нетривиальные действия
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877957
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Станислав КлевцовЗдравствуйте.

Есть описание идиомы на WIKIPEDIA
https://ru.wikipedia.org/wiki/Идиома_copy-and-swap

Кто - нибудь может объяснить тоже самое, но только в двух словах и более простом языком ?


По-моему, там всё предельно понятно расписано.
Единственно, что текст немного устарел, поскольку спецификация throw уже объявлена устаревшей.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877970
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite OwlВо первых, никто не гарантирует что конструктор копирования написан правильно (а не точно так как я показал в примере кривого оператора присваивания).
Написать конструктор правильно намного проще, чем присвоение.



На самом деле после появления placement new конструктор стал более похож на оператор присваивания, и они почти сравнялись.
Почти -- потому что по стандарту программирс обязан после вызова placement new вызвать сам руками деструктор объекта.
Но всё равно никто не запрещает возложить на конструктор такую же семантику, как на оператор присваивания, и не вызывать деструктор.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38877980
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlAnatoly Moskovskyпропущено...

Написать конструктор правильно намного проще, чем присвоение.Почему? В чем разница?



Изначально в языке у них была разная семантика.

Конструктор инициализирует объект, а это значит, что до этого объекта в этой памяти (*this) не было, и его не надо деинициализировать.

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

Кроме этого, конструктор копирования нельзя вызывать от самого себя (потому что бессмысленно, в принципе -- можно, но на это никто не закладывается), а оператор присваивания самому себе вполне может быть.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38878154
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНа самом деле после появления placement new конструктор стал более похож на оператор присваивания, и они почти сравнялись.
Почти -- потому что по стандарту программирс обязан после вызова placement new вызвать сам руками деструктор объекта.
Но всё равно никто не запрещает возложить на конструктор такую же семантику, как на оператор присваивания, и не вызывать деструктор

Введение placement new ничего не добавило принципиального. С обычным new вызов деструктора тоже вручную производится - оператором delete

И это все никакого отношения к обсуждаемому вопросу не имеет.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38878226
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyMasterZivНа самом деле после появления placement new конструктор стал более похож на оператор присваивания, и они почти сравнялись.
Почти -- потому что по стандарту программирс обязан после вызова placement new вызвать сам руками деструктор объекта.
Но всё равно никто не запрещает возложить на конструктор такую же семантику, как на оператор присваивания, и не вызывать деструктор

Введение placement new ничего не добавило принципиального. С обычным new вызов деструктора тоже вручную производится - оператором delete

И это все никакого отношения к обсуждаемому вопросу не имеет.

Подумай лучше ...
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38878583
Фотография Станислав Клевцов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyСтанислав Клевцов,

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

2) Решение.
Сначала создать временный объект, копию того из которого присваивается.
Если на этом этапе произойдет исключение, то текущий объект пока еще не изменен и несогласованности нет.
Потом производится обмен полей временного объекта с полями конечного объекта путем простого побайтового копирования. Такое копирование не может выбросить исключение и оно почти не вносит дополнительных расходов.
На завершающем этапе присвоения вызовется деструктор временного объекта и очистит поля ранее принадлежавшие конечному объекту.

Таким образом данное решение позволяет всегда иметь объекты в согласованном состоянии.

Спасибо, Анатолий и White Owl ! Стало намного понятнее. Еще раз спасибо.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38879303
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Несколько мыслей.

Интересно насколько нужно много (или мало) внимания уделять вообще самому факту
возникновения подобной ситуации. Память может закончится в любой момент. Это факт.
Но сколько мы должны потратить человеко-лет чтобы весь код покрыть подобной идеомой?
Или отрефакторить.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38879326
RWolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

Исключение здесь необязательно связано с памятью, это может быть неудачное завершение транзакции, захват/освобождение ресурса, ошибка RPC и т.п.
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38879333
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonИнтересно насколько нужно много (или мало) внимания уделять вообще самому факту
возникновения подобной ситуации. Память может закончится в любой момент. Это факт.

Исключения выкидываются далеко не только по нехватке памяти и прочих ресурсов.
При присвоении полей могут возникать и "прикладные" исключения.

maytonНо сколько мы должны потратить человеко-лет чтобы весь код покрыть подобной идеомой?
Или отрефакторить.
Так можно и не переделывать, если вас и так устраивала надежность приложения до того как вы про эту идиому узнали ))
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38879396
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Столько заморочек только чтобы присваивать сами объекты вместо указателей на них... Для
кого, спрашивается смарт-указатели в стандарт ввели?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38879419
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

А если вам нужны два разных объекта, как тут смартуказатели помогут?
...
Рейтинг: 0 / 0
Идиома copy-on-swap С++
    #38879423
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyА если вам нужны два разных объекта, как тут смартуказатели
помогут?
Точно так же как в сабже: если создание нового объекта обломилось во время работы
копи-конструктора, указатель не присвоится и компилятор с деструктором позаботятся о
зачистке обломков.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
25 сообщений из 39, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Идиома copy-on-swap С++
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]