перехват объектов исключений по ссылкам, временным изменениям, проблемам времени жизни - PullRequest
5 голосов
/ 07 декабря 2009

Рассмотрим следующий код:

#include <iostream>
#include <stdexcept>

void foo()
{
    throw std::runtime_error("How long do I live?");
}

int main()
{
    try
    {
        foo();
    }
    catch (std::runtime_error& e)
    {
        std::cout << e.what() << std::endl;
    }
}

Почему я могу поймать исключение по ссылке, разве std::runtime_error("How long do I live?") не является значением?

Почему объект исключения все еще жив в блоке catch?

Где именно хранятся объекты исключенных исключений? Какова их продолжительность жизни?

Ответы [ 4 ]

7 голосов
/ 07 декабря 2009

В стандарте C ++, пункт 15.1.4:

Память для временной копии исключение бросается распределяется неопределенным образом, за исключением случаев, указанных в 3.7.3.1. The временный сохраняется до тех пор, пока есть для этого выполняется обработчик исключение . В частности, если обработчик выходит, выполняя бросок; заявление, которое передает контроль другой обработчик для того же исключение, поэтому временное остается. Когда последний обработчик выполняется за исключением выходов любым способом кроме броска; временный объект уничтожается и реализация может освободить память для временный объект; Любое такое освобождение сделано в неуказанном путь. Происходит разрушение сразу после уничтожения объект объявлен в объявление исключения в обработчике.

Обратите внимание, что в C ++ - стандартном разговоре обработчик обозначает блок catch с правильным типом аргумента.

5 голосов
/ 07 декабря 2009

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

[править] Я просто проверяю стандарт, и это на самом деле относится к временной копии. Тем не менее, гарантируется, что время жизни временного файла будет не меньше, чем у обработчика исключений.

2 голосов
/ 07 декабря 2009

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

1 голос
/ 07 декабря 2009

Слава за попытку понять детали языка. В то же время, ИМХО, гораздо важнее понять, почему вы должны перехватить исключение по ссылке (и выбросить его по значению), чем почему вы можете .

Люди обычно используют иерархию классов исключений, а перехват по ссылке позволяет использовать полиморфизм и перехватывать исключение базового класса, когда нет необходимости обрабатывать отдельные типы исключений отдельно. Если вы не смогли отловить по ссылке, вам пришлось бы написать предложение catch для каждого возможного типа исключения, которое может быть выброшено в предложении try.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...