Гарантии при выбросе исключений
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Абсолютная гарантия (nothrow or nofail exception guarantee) – функция не бросает исключения не при каких обстоятельствах, ошибки сигнализируются с помощью возвращаемых значений, глобальных переменных (errno) или подавляются. Такую гарантию должны давать функции типа swap, перемещающие конструкторы и перемещающие операторы присваивания, а также другие функции, вызываемые в деструкторах при раскрутке стека.

Сильная гарантия (strong exception guarantee) – если функция выбрасывает исключение программа возвращается к состоянию предшествующему вызову данной функции («все» или «ничего») – транзакционное поведение

Базовая гарантия (basic exception guarantee) – по выбросу исключения программа в корректном состоянии но может потребоваться дополнительная очистка, инварианты сохранены

Нет гарантий (no exception guarantee) – функция ничего не гарантирует, возможна утечка ресурсов или повреждение данных в памяти или программа окажется в некорректном состоянии, сохранение инвариантов не гарантируется

 

Перехват исключений

Исключения, находящиеся внизу иерархии наследования должны перехватываться первыми

void f() {

try {

//...

} catch (overflow_error) {

//...

} catch (runtime_error) {

//...

} catch (bad_alloc){

//...

} catch (exception){

//...

} catch (...) {

//...

}

Обработка исключений

Для перехвата исключения с возможностью работы с ним, необходимо в блоке catch использовать переменную – формальный параметр:

try {

...

} catch (exception &dafaq) {

cout<<dafaq.what();

}

 

С целью повторной генерации исключения необходимо использовать оператор throw без параметров:

                                                                                                                                                                              

try {

...

} catch (exception &dafaq) {

cout<<dafaq.what();

throw; //повторный выброс исключения

}

 

Так как механизм обработки исключений работает во время исполнения программы, а не ее компиляции, он замедляет работу программы. Для того, чтобы уменьшить издержки на обработку исключений, в обработчике нужно использовать ссылки, дабы сократить количество создаваемых/уничтожаемых объектов.

 

Если во время раскрутки стека выброшено новое исключение, то механизм обработки вызывает функцию terminate, которая завершает программу посредством вызова функци abort. Поэтому выбрасывать исключения из деструкторов не рекомендуется, т.к. они могут вызваться во время раскрутки стека.

       Функция terminate()

❑ Вызывается при разрушении стека:

❑ если выбрасывается исключение во время обратной раскрутки стека при уже выброшенном исключении

❑ если вызывается throw; вне блока перехвата исключения (повторная генерация если выброса исключения не было)

❑ если произошло исключение но не было перехвачено

❑ если конструктор глобального статического объекта завершается аварийно с выбросом исключения

❑ По умолчанию terminate() вызывает abort()*

* Функция abort() вызывает немедленное прекращение программы.

 

Умные указатели:

o unique_ptr<T> - эксклюзивное владение указателем на объект типа T с возможностью передачи владения другому unique_ptr, поддерживает определенный пользователем «уничтожитель» - Deleter (опция)

o shared_ptr<T> - общее владение указателем на объект с подсчетом ссылок, семантикой копирования, возможностью преобразования

o weak_ptr<T> - позволяет работать с указателем, управляемым shared_ptr без «владения»

 

UNIQUE

 

std::unique_ptr – умный указатель, который:

§ получает единоличное владение объектом через его указатель, и

§ разрушает объект через его указатель, когда unique_ptr выходит из области видимости.

unique_ptr не может быть скопирован или задан через операцию присвоения. Неконстантный unique_ptrможет передать владение управляемым объектом другому указателю unique_ptr.

const std::unique_ptr не может быть передан, ограничивая время жизни управляемого объекта областью, в которой указатель был создан. Когда unique_ptr уничтожается, он удаляет объект с помощью Deleter.

Существует две версии std::unique_ptr:

1) управляет временем жизни одного объекта, например, созданного с помощью оператора new

2) управляет временем жизни массива, с длиной, определенной во время выполнения, созданного с помощью new[]

Типичные случаи применения std::unique_ptr включают:

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

§ передача владения динамически созданным объектом в функции

§ получение владения динамически созданным объектом из функций

§ в качестве типа элемента в контейнерах, поддерживающих семантику перемещения, таких как std::vector, которые хранят указатели на динамически выделенные объекты (например, если желательно полиморфное поведение)

Для массива:

 

std::unique_ptr<int[]> ptr(new int[10]);

  for (int i = 0; i < 10; i++)

        ptr[i] = 2 * i;

 

 

Пример реализации своего deleter для смарт указателей:

class TextureDeleter

{

public:

TextureDeleter()

{}

 

void operator()(SDL_Texture *ptr) const

{

           SDL_DestroyTexture(ptr);

}      

~TextureDeleter()

{}

};

 

void foo()

{

...................

std::unique_ptr<SDL_Texture, TextureDeleter> a(IMG_LoadTexture(canvas, name.str().c_str()), TextureDeleter());

textures["walls"].push_back(std::move(a));

   ...................

}

 

 

Shared

std::shared_ptr – умный указатель, с разделяемым владением объектом через его указатель. Несколько указателей shared_ptr могут владеть одним и тем же объектом; объект будет уничтожен, когда последний shared_ptr, указывающий на него, будет уничтожен или сброшен. Объект уничтожается с использованием delete-expression или с использованием пользовательской функции удаления объекта, переданной в конструктор shared_ptr.

shared_ptr может не владеть ни одним объектом, в этом случае он называется пустым.

 

std::shared_ptr<int> sptr(new int);

  {

        std::shared_ptr<int> p2 = sptr;    //умрет после выхода из блока

        std::cout << sptr.unique() << std::endl;

  }

std::cout << sptr.unique() << std::endl;

 

Выведет: 0

        1

      

Weak

std::weak_ptr – умный указатель, который содержит "слабую" ссылку на объект, управляемый указателем std::shared_ptr. Чтобы получить доступ к управляемому объекту, указатель необходимо привести к типу std::shared_ptr, .

std::weak_ptr моделирует временное владение: когда объект должен быть доступен только если он существует и может быть удален в любой момент кем-то другим, std::weak_ptr используется для отслеживания объекта, и преобразуется в std::shared_ptr для принятия временного владения. Если исходный std::shared_ptr будет уничтожен в процессе работы, время жизни объекта продлевается до того момента, пока не будет разрушен временный std::shared_ptr.

Помимо этого, std::weak_ptr используется для устранения циклических ссылок std::shared_ptr.

void f()

{

if (auto p = wp.lock())

      std::cout << *p << std::endl;

   else

           std::cout << "Shit, it died!" << std::endl;

}

 

int main()

{

       

   {

      std::shared_ptr<int> sp(new int);

      *sp = 5;

           wp = sp;

           f();

        }

f();

    return 0;

}

Выведет : 5

Shit, it died!

 

Дата: 2019-02-19, просмотров: 265.