WikiSort.ru - Программирование

ПОИСК ПО САЙТУ | о проекте

Идиома copy-and-swap — это идиома языка программирования C++, позволяющая разрабатывать устойчивые к исключениям операторы присваивания.

Идиома базируется на идиоме «Получение ресурса есть инициализация».

Идиома предполагает реализацию следующих функций-членов класса:

  • конструктора копирования;
  • оператора присваивания;
  • метода swap, не генерирующего исключения и принимающего ссылку на объект класса.

Пример:

class Copyable {
public:
   Copyable& operator=(const Copyable &_v) {
      Copyable tmp(_v);
      this->swap(tmp);
      return *this;
   }

   void swap(Copyable &_v) noexcept;
};

Устойчивость к исключениям заключается в том, что в операторе присваивания Copyable& operator=(const Copyable &) нет точки, где генерация исключения могла бы привести к утечке памяти.

Оператор присваивания сначала пытается захватить ресурс «временная копия присваиваемого объекта» (tmp) и в случае успеха меняет его содержимое с содержимым текущего объекта (this). Поскольку метод swap объявлен как не генерирующий исключения (noexcept), единственной точкой, где может возникнуть исключение, является копирование объекта _v. Если копирование не удается, то управление не доходит до метода swap, в противном случае деструктор объекта tmp освобождает ресурсы, прежде принадлежавшие текущему объекту (this) (см. идиому RAII).

Приведённая выше реализация также устойчива к присваиваниям объекта самому себе (a=a), однако содержит издержки, связанные с тем, что временная копия в этом случае тоже будет создаваться. Исключить издержки можно дополнительной проверкой:

class Copyable {
public:
   Copyable& operator=(const Copyable &_v) {
      if(this != &_v)
          Copyable(_v).swap(*this);
      return *this;
   }

   void swap(Copyable &_v) noexcept;
};

Многие контейнеры и алгоритмы стандартной библиотеки C++ и библиотеки STL предполагают наличие устойчивого к исключениям оператора присваивания, но без использования идиомы copy-and-swap иногда довольно сложно реализовать такой оператор присваивания для классов, содержащих, например, указатели на экземпляры других классов.

Другие операции

Имея функцию-член swap, не генерирующую исключений, можно применять подобную технику, чтобы сделать любую операцию над объектом строгой в отношении к гарантиям безопасности исключений (strong exception-safe guarantee).

Для этого сначала делают копию существующего объекта, выполняют над копией необходимые модификации, а потом меняют *this и временный объект.

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

См. также

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

Другой контент может иметь иную лицензию. Перед использованием материалов сайта WikiSort.ru внимательно изучите правила лицензирования конкретных элементов наполнения сайта.

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии