Как работают метания и ловли?

14

С этим кодом:

int main()
{
    try
    {
        throw -1;
    }
    catch (int& x)
    {
        std::cerr << "We caught an int exception with value: " << x << std::endl;
    }
    std::cout << "Continuing on our merry way." << std::endl;

    return 0;
}

У нас есть:

/tmp$ ./prorgam.out
Continuing on our merry way
We caught an int exception with value: -1

Как catchблок читается -1как int&? Мы не могли присвоить значение неконстантной ссылке на lvalue.

И почему второе std::coutутверждение выполняется перед первым std::cerrутверждением?

Гасем Рамезани
источник
2
Вы уверены, что это именно то, что вы получили? We caught an int exception with value: -1Линия должна быть напечатана первой.
HolyBlackCat
1
@Scheff, извините, вы правы, первый вывод перенаправлен на error streamнет standard stream.
Гасем Рамезани
2
@ FrançoisAndrieux Причина, по которой это разрешено, заключается в том, что существует разная семантика. Обычно с временным вы не знаете, что произойдет с ним, поэтому было решено разрешить только постоянные ссылки на временные. За исключением того, что мы знаем время жизни объекта, и мы можем захотеть изменить его и перебросить в более высокий контекст. Чтобы облегчить это, стандарт допускает привязку к неконстантной lvalue ссылке.
Натан Оливер
1
@ FrancoisAndrieux throwсоздает копию (или перемещает) объект, который вы ему передаете. Ссылка привязывается к этой копии. Это имеет смысл, что копия является lvalue.
HolyBlackCat

Ответы:

10

Это нормально из-за [кроме. Броска] / 3

Вызов исключительной копии инициализирует ([dcl.init], [class.copy.ctor]) временный объект, называемый объектом исключения. Значение l, обозначающее временное значение, используется для инициализации переменной, объявленной в соответствующем обработчике ([исключением. Дескриптор]).

акцент мой

Как вы можете видеть, хотя это и временно, компилятор обрабатывает его как lvalue для инициализации обработчика. Из-за этого вам не нужна постоянная ссылка.

NathanOliver
источник
1
Но что за порядок, в котором появляются сообщения?
Томаш Зато - Восстановить Монику
8

Из этой throwссылки :

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

Таким образом, хотя «объект» является временным, он все еще является lvalue, и поэтому вы можете перехватить его по ссылке.

Какой-то программист чувак
источник