Выбросить исключение по значению или ссылке

Из этого ответа https://stackoverflow.com/a/36738405/4523099:

Выражение throw без операнда повторно создает обрабатываемое в данный момент исключение. Исключение повторно активируется с существующим временным; новый объект временного исключения не создается. -- ISO/IEC 14882:2011, раздел 15.1, пар. 8

Итак, почему я получаю эти результаты из этого кода?

код:

#include <iostream>

class my_exception: public std::exception{
public:
    int value;
};
int main()
{
    my_exception ex;
    ex.value=1;
    try{
        throw ex;
    }
    catch(my_exception& e){
        e.value=2;
    }
    std::cout << ex.value;
   return 0;
}

Фактический результат:

1

Я думал, что должно быть 2 в зависимости от стандартной квоты. Что мне не хватает?


person Humam Helfawi    schedule 20.04.2016    source источник
comment
Выражение throw без операнда — это throw; (в блоке catch).   -  person Jarod42    schedule 20.04.2016


Ответы (2)


Это связано с тем, что throw (обычная версия) создает копию :

Во-первых, копия-инициализирует объект исключения из выражения (это может вызвать конструктор перемещения для выражения rvalue, а копирование/перемещение может быть предметом исключения копирования),...

и сохранить его внутри, поэтому e.value=2; изменяет внутреннюю копию.

В SO вы упоминаете вопрос о версии с повторным броском, которая не создает новую копию, а использует уже существующую внутреннюю копию.

person marcinj    schedule 20.04.2016

Только повторный бросок (без операнда) повторно использует один и тот же объект исключения. Вот некоторый код, чтобы продемонстрировать это:

#include <iostream>

class my_exception: public std::exception{
public:
    int value;
};

void f(my_exception& ex) {
    ex.value = 1;
    try {
        throw ex;
    } catch (my_exception& e) {
        e.value = 2;
        // Here's the re-throw
        throw;
    }
}

int main()
{
    my_exception ex;
    try {
        f(ex);
    } catch (my_exception& e) {
        std::cout << e.value;
    }
    return 0;
}
person Toby Speight    schedule 20.04.2016