Отправляет email-рассылки с помощью сервиса Sendsay
Открытая группа
27 участников
Администратор Legotckoi
Модератор ProgrammersBlog

Последние откомментированные темы:

20250419000257

←  Предыдущая тема Все темы Следующая тема →
пишет:

Аннотация на статью: Декларативное программирование в С++

Понравилась заметка на habrahabr по декларативному программированию в С++: https://habrahabr.ru/post/270545/. (загляните в конец аннотации).

1) В статье говорится, что использовать напрямую try-catch - не очень хорошая идея, т.к. код будет нечитабельным (об этом же можно узнать почитав другие статьи по теме RAII-классов).

2) в статье описывается решение (уже лежит в boost 10 лет, но сейчас об этом говорят на конференциях по С++ достаточно много). Схематично показано как это решение внутри устроено - это особенно понравилось.

3) Дополнение (содержит мое личное мнение и с автором статьи не связано). Что касается примера из статьи - я бы (хотя кто я такой?) заменил его на что-то типа
int *a = new int[25];
int *b = new int[25];

Проблема примера точно такая же как и в примере из статьи (но такой код гигабайтами пишут студенты и поэтому им будет понятно о чем речь) - оператор new может выкинуть исключение. Если bad_alloc вылетит при первом new - то утечки не будет, а при втором - будет.

Решение проблемы очевидно - использовать RAII классы, например вектор. Если объект создается на стеке и если будет выработано исключение - стек "разматывается" и для таких объектов вызываются деструкторы.

vector<int> a;
vector<int> b;

Тут утечки не будет. В стандартной библиотеке С++ есть куча готовых классов, поддерживающих идиому RAII - fstream сам закроет файл, unique_ptr (и все прочие умные указатели) сам освободит память при выходе из функции (в т.ч. по исключению) и т.п. Очевидно, что RAII работает прекрасно и про это можно прочитать:

4) Ну а что же делать, если при возникновении исключения надо выполнять какие-то нестандартные действия? (Еще одна проблема) - не городить же каждый раз RAII-класс? На самом деле, пример когда это нужно привести не так просто, в примере из статьи проблема могла бы быть решена использованием std::string (тоже RAII класс). Но допустим, такая ситуация возникает.

В качестве решения Александреску предложил идиому Scope Guard. Boost реализует ее и предлагает использовать макросы типа SCOPE_FAIL, которые создают на стеке анонимную переменную, для которой будет вызван деструктор при возникновении исключения. Ну и к этой переменной привязывают лямбду, которая и будет вызвана в деструкторе. Решение в бусте чуть сложнее, т.к. деструктор проверяет причины возникновения исключения (наша лямбда вызывается не во всех случаях).

Некоторые детали реализации можно найти в статье.

Это интересно
0

29.11.2017
Пожаловаться Просмотров: 320  
←  Предыдущая тема Все темы Следующая тема →


Комментарии временно отключены