Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Есть описание идиомы на WIKIPEDIA https://ru.wikipedia.org/wiki/Идиома_copy-and-swap Кто - нибудь может объяснить тоже самое, но только в двух словах и более простом языком ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.02.2015, 23:26 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Станислав Клевцов, 1) Проблема. При реализации операторов присвоения, при присвоении поэлементно полей класса в определенный момент может возникнуть исключение (например нехватка памяти) и часть полей останется присвоенной, а часть нет. Объект при этом может оказаться в несогласованном состоянии - часть полей относится к старому объекту, часть к новому. Часто при этом могут быть потеряны неосвобожденные указатели на кучу. 2) Решение. Сначала создать временный объект, копию того из которого присваивается. Если на этом этапе произойдет исключение, то текущий объект пока еще не изменен и несогласованности нет. Потом производится обмен полей временного объекта с полями конечного объекта путем простого побайтового копирования. Такое копирование не может выбросить исключение и оно почти не вносит дополнительных расходов. На завершающем этапе присвоения вызовется деструктор временного объекта и очистит поля ранее принадлежавшие конечному объекту. Таким образом данное решение позволяет всегда иметь объекты в согласованном состоянии. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 00:35 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Иными словами проблема высосана из пальца. И ее решение хоть и достаточно элегантно, но не имеет смысла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 00:45 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
White OwlИными словами проблема высосана из пальца Это вполне реальная проблема. Конечно с точки зрения С-шника, необходимость вручную убирать выделенную память не является проблемой. Но в С++ концепция другая - главная цель создания С++ - переложить всю ручную работу на компилятор. Данная идиома показывает как это сделать проще всего для конкретной задачи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 01:18 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
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. И теперь, если одно из присвоений внутри operator=() упало, то в последней строке состояние b будет неопределенным. Было заполнено str1? str2? или еще что-то упало? В каком объеме надо очищать b? Я правильно понимаю вашу проблему? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 01:22 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
White OwlИ теперь, если одно из присвоений внутри operator=() упало, то в последней строке состояние b будет неопределенным. Было заполнено str1? str2? или еще что-то упало? В каком объеме надо очищать b? Я правильно понимаю вашу проблему? Да, обычно новички каждый раз заново придумывают как реализовать оператор =. И чаще всего, как и в вашем случае, он неверно реализован. Например, не удаляется предыдущее значение полей. И прочее. Чтобы не придумывать каждый раз, данная идиома показывает как тривиально реализовать =, который автоматически не имеет указанных проблем и заодно не требует перехвата исключений. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 01:32 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyWhite OwlИ теперь, если одно из присвоений внутри operator=() упало, то в последней строке состояние b будет неопределенным. Было заполнено str1? str2? или еще что-то упало? В каком объеме надо очищать b? Я правильно понимаю вашу проблему? Да, обычно новички каждый раз заново придумывают как реализовать оператор =. И чаще всего, как и в вашем случае, он неверно реализован. Например, не удаляется предыдущее значение полей. И прочее. Чтобы не придумывать каждый раз, данная идиома показывает как тривиально реализовать =, который автоматически не имеет указанных проблем и заодно не требует перехвата исключений.Не требует? Точно? То есть ты утверждаешь что если оператор присваивания переписать через copy-and-swap, то исключения возникнуть не смогут? А исключения которые могут возникнуть внутри конструктора копирования (и по тем-же самым причинам) ты в расчет не принимаешь? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 01:52 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
White OwlТо есть ты утверждаешь что если оператор присваивания переписать через copy-and-swap, то исключения возникнуть не смогут? Могут. White OwlА исключения которые могут возникнуть внутри конструктора копирования (и по тем-же самым причинам) ты в расчет не принимаешь? Да, не принимаю, т.к. это забота конструктора копирования (который по-любому нужно реализовать если требуется оператор=), и к тому же в правильно написанном конструкторе компилятор сам заботится о исключениях. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 02:08 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
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 можно в обоих случаях и с одинаковым результатом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 02:47 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
White OwlВо первых, никто не гарантирует что конструктор копирования написан правильно (а не точно так как я показал в примере кривого оператора присваивания). Написать конструктор правильно намного проще, чем присвоение. White OwlВо вторых, для copy-and-swap надо еще написать правильный метод swap. Что тоже не всегда тривиально. Нет. Всегда тривиально. Код: plaintext 1. 2. 3. 4. 5. 6. 7. Если это нетривиально, то что тогда тривиально )) White OwlВ третьих, даже если конструктор копирования и swap() написаны правильно - конструктор все равно может упасть. И значит каждый a=b; надо оборачивать в try{}catch (или ловить исключение выше по стеку). Нет. Не надо оборачивать ничего. Исключения ловятся там где это задумано по дизайну приложения, а не в операторе присвоения из-за неумения написать его правильно - это и есть цель которая достигается данной идиомой White OwlВывод: используешь ты этот патерн или нет разницы никакой нет. Без него тебе надо продуманно писать operator=() и конструктор копирования. С ним тебе надо продуманно писать конструктор копирования и swap(). Работы в итоге получается практически одинаково. Упасть на a=b можно в обоих случаях и с одинаковым результатом. Садитесь два. Изучайте заново материал )) ЗЫ. White Owl, критика всегда уместна. Критиковать можно даже то, в чем не разбираешься. Но не надо облекать это в форму советов бывалого и тем более заниматься дартаньянизмом :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 03:11 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyWhite OwlВо первых, никто не гарантирует что конструктор копирования написан правильно (а не точно так как я показал в примере кривого оператора присваивания). Написать конструктор правильно намного проще, чем присвоение.Почему? В чем разница? Anatoly MoskovskyWhite OwlВо вторых, для copy-and-swap надо еще написать правильный метод swap. Что тоже не всегда тривиально. Нет. Всегда тривиально. Код: plaintext 1. 2. 3. 4. 5. 6. 7. Если это нетривиально, то что тогда тривиально ))Тривиально это отсутствие метода. А в данном случае нетривиально то, что надо не забыть перечислить все поля. И это только в минимуме, если используемые ресурсы это исключительно куски памяти. А если копируемые ресурсы что-то более сложное (ну хоть хендлы на файлы или мютексы) то простым std::swap уже не отделаешься. Anatoly MoskovskyWhite OwlВ третьих, даже если конструктор копирования и swap() написаны правильно - конструктор все равно может упасть. И значит каждый a=b; надо оборачивать в try{}catch (или ловить исключение выше по стеку). Нет. Не надо оборачивать ничего. Исключения ловятся там где это задумано по дизайну приложения, а не в операторе присвоения из-за неумения написать его правильно - это и есть цель которая достигается данной идиомойХорошо. Вот в этом посте 17253298 , я показал не правильный код. Покажи мне правильный код пожалуйста. Приведи правильный код класса который никогда не сможет упасть на присвоении. Anatoly MoskovskyЗЫ. White Owl, критика всегда уместна. Критиковать можно даже то, в чем не разбираешься. Но не надо облекать это в форму советов бывалого и тем более заниматься дартаньянизмом :)Cura te ipsum ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 07:10 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
White OwlAnatoly MoskovskyНаписать конструктор правильно намного проще, чем присвоение.Почему? В чем разница? 1) в конструкторе не надо очищать старые значения (что уже проще) 2) при исключении в конструкторе, автоматически вызываются деструкторы тех полей, которые инициализированы на момент исключения (что намного проще, чем руками откатывать значения в =) White OwlТривиально это отсутствие метода. А в данном случае нетривиально то, что надо не забыть перечислить все поля. И это только в минимуме, если используемые ресурсы это исключительно куски памяти. А если копируемые ресурсы что-то более сложное (ну хоть хендлы на файлы или мютексы) то простым std::swap уже не отделаешься. Если swap не работает на одном из полей, то в такой объект вообще нельзя присваивать. Хотя в частности ваш пример с хендлами такого ограничения не имеет - ничего не мешает делать хендлу swap. White OwlПриведи правильный код класса который никогда не сможет упасть на присвоении. Господи, ну нет такой задачи не упасть. Задача - при исключении оставить объект в согласованном состоянии, чтобы после перехвата исключения где-то там наверху можно было продолжить работу с объектом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 11:46 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
White OwlА в данном случае нетривиально то, что надо не забыть перечислить все поля. А также не забыть включить компьютер, сохранить файл перед компиляцией, и другие нетривиальные действия ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 11:49 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Станислав КлевцовЗдравствуйте. Есть описание идиомы на WIKIPEDIA https://ru.wikipedia.org/wiki/Идиома_copy-and-swap Кто - нибудь может объяснить тоже самое, но только в двух словах и более простом языком ? По-моему, там всё предельно понятно расписано. Единственно, что текст немного устарел, поскольку спецификация throw уже объявлена устаревшей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 13:20 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyWhite OwlВо первых, никто не гарантирует что конструктор копирования написан правильно (а не точно так как я показал в примере кривого оператора присваивания). Написать конструктор правильно намного проще, чем присвоение. На самом деле после появления placement new конструктор стал более похож на оператор присваивания, и они почти сравнялись. Почти -- потому что по стандарту программирс обязан после вызова placement new вызвать сам руками деструктор объекта. Но всё равно никто не запрещает возложить на конструктор такую же семантику, как на оператор присваивания, и не вызывать деструктор. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 13:25 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
White OwlAnatoly Moskovskyпропущено... Написать конструктор правильно намного проще, чем присвоение.Почему? В чем разница? Изначально в языке у них была разная семантика. Конструктор инициализирует объект, а это значит, что до этого объекта в этой памяти (*this) не было, и его не надо деинициализировать. Оператор присваивания присваивает, т.е. замещает состояние данного валидного объекта на другое состояние, и для этого нужно старое состояние корректно изничтожить (почти полный аналог деструктора, но есть разница). Кроме этого, конструктор копирования нельзя вызывать от самого себя (потому что бессмысленно, в принципе -- можно, но на это никто не закладывается), а оператор присваивания самому себе вполне может быть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 13:30 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
MasterZivНа самом деле после появления placement new конструктор стал более похож на оператор присваивания, и они почти сравнялись. Почти -- потому что по стандарту программирс обязан после вызова placement new вызвать сам руками деструктор объекта. Но всё равно никто не запрещает возложить на конструктор такую же семантику, как на оператор присваивания, и не вызывать деструктор Введение placement new ничего не добавило принципиального. С обычным new вызов деструктора тоже вручную производится - оператором delete И это все никакого отношения к обсуждаемому вопросу не имеет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 15:11 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyMasterZivНа самом деле после появления placement new конструктор стал более похож на оператор присваивания, и они почти сравнялись. Почти -- потому что по стандарту программирс обязан после вызова placement new вызвать сам руками деструктор объекта. Но всё равно никто не запрещает возложить на конструктор такую же семантику, как на оператор присваивания, и не вызывать деструктор Введение placement new ничего не добавило принципиального. С обычным new вызов деструктора тоже вручную производится - оператором delete И это все никакого отношения к обсуждаемому вопросу не имеет. Подумай лучше ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 15:46 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyСтанислав Клевцов, 1) Проблема. При реализации операторов присвоения, при присвоении поэлементно полей класса в определенный момент может возникнуть исключение (например нехватка памяти) и часть полей останется присвоенной, а часть нет. Объект при этом может оказаться в несогласованном состоянии - часть полей относится к старому объекту, часть к новому. Часто при этом могут быть потеряны неосвобожденные указатели на кучу. 2) Решение. Сначала создать временный объект, копию того из которого присваивается. Если на этом этапе произойдет исключение, то текущий объект пока еще не изменен и несогласованности нет. Потом производится обмен полей временного объекта с полями конечного объекта путем простого побайтового копирования. Такое копирование не может выбросить исключение и оно почти не вносит дополнительных расходов. На завершающем этапе присвоения вызовется деструктор временного объекта и очистит поля ранее принадлежавшие конечному объекту. Таким образом данное решение позволяет всегда иметь объекты в согласованном состоянии. Спасибо, Анатолий и White Owl ! Стало намного понятнее. Еще раз спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.02.2015, 22:38 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Несколько мыслей. Интересно насколько нужно много (или мало) внимания уделять вообще самому факту возникновения подобной ситуации. Память может закончится в любой момент. Это факт. Но сколько мы должны потратить человеко-лет чтобы весь код покрыть подобной идеомой? Или отрефакторить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.02.2015, 16:30 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
mayton, Исключение здесь необязательно связано с памятью, это может быть неудачное завершение транзакции, захват/освобождение ресурса, ошибка RPC и т.п. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.02.2015, 16:48 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
maytonИнтересно насколько нужно много (или мало) внимания уделять вообще самому факту возникновения подобной ситуации. Память может закончится в любой момент. Это факт. Исключения выкидываются далеко не только по нехватке памяти и прочих ресурсов. При присвоении полей могут возникать и "прикладные" исключения. maytonНо сколько мы должны потратить человеко-лет чтобы весь код покрыть подобной идеомой? Или отрефакторить. Так можно и не переделывать, если вас и так устраивала надежность приложения до того как вы про эту идиому узнали )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.02.2015, 17:01 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Столько заморочек только чтобы присваивать сами объекты вместо указателей на них... Для кого, спрашивается смарт-указатели в стандарт ввели?.. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.02.2015, 18:02 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakov, А если вам нужны два разных объекта, как тут смартуказатели помогут? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.02.2015, 18:28 |
|
||
|
Идиома copy-on-swap С++
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyА если вам нужны два разных объекта, как тут смартуказатели помогут? Точно так же как в сабже: если создание нового объекта обломилось во время работы копи-конструктора, указатель не присвоится и компилятор с деструктором позаботятся о зачистке обломков. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.02.2015, 18:36 |
|
||
|
|

start [/forum/topic.php?fid=57&fpage=50&tid=2019108]: |
0ms |
get settings: |
9ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
40ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
125ms |
get tp. blocked users: |
2ms |
| others: | 284ms |
| total: | 490ms |

| 0 / 0 |
