Jak działa rzucanie i łapanie ints?

14

Z tym kodem:

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;
}

Mamy:

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

W jaki sposób catchblok czytać -1jak int&? Nie można przypisać wartości do nieistniejącego odwołania do wartości.

I dlaczego druga std::coutinstrukcja jest wykonywana przed pierwszą std::cerrinstrukcją?

Ghasem Ramezani
źródło
2
Czy jesteś pewien, że otrzymujesz dokładnie taką wydajność? We caught an int exception with value: -1Linia powinna być pierwszy wydrukowany.
HolyBlackCat,
1
@Scheff, Przepraszamy, masz rację, Pierwsze wyjście jest przekierowane na error streamnie standard stream.
Ghasem Ramezani,
2
@ FrançoisAndrieux Powodem, dla którego jest to dozwolone, jest istnienie innej semantyki. Zasadniczo z tymczasowym nie wiesz, co się z nim stanie, dlatego postanowiono zezwolić na stałe odwołania tylko do tymczasowych. Z wyjątkami znamy czas życia obiektu i możemy chcieć go zmodyfikować i przywrócić do wyższego kontekstu. Aby to ułatwić, standard pozwala na powiązanie z nie-stałą wartością odniesienia.
NathanOliver,
1
@ FrançoisAndrieux throwtworzy kopię (lub przenosi) przekazywany do niej obiekt. Odwołanie wiąże się z tą kopią. To ma sens, że kopia jest wartością.
HolyBlackCat,

Odpowiedzi:

10

Jest to w porządku z powodu [wyjątkiem. Rzut] / 3

Zgłoszenie wyjątku copy-initialize ([dcl.init], [class.copy.ctor]) obiekt tymczasowy, zwany obiektem wyjątku. Wartość określająca wartość tymczasową służy do inicjalizacji zmiennej zadeklarowanej w odpowiednim module obsługi ([oprócz uchwytu]).

mój nacisk

Jak widać, nawet jeśli jest to tymczasowy, kompilator traktuje go jako wartość do zainicjowania modułu obsługi. Z tego powodu nie potrzebujesz stałej referencji.

NathanOliver
źródło
1
Ale w jakiej kolejności pojawiają się komunikaty?
Tomáš Zato - Przywróć Monikę
8

Z tego throwodniesienia :

W odróżnieniu od innych obiektów tymczasowych, obiekt wyjątku jest uważany za argument wartości wartości podczas inicjowania parametrów klauzuli catch, dzięki czemu można go przechwycić przez odwołanie do wartości, zmodyfikować i ponownie wprowadzić.

Tak więc „obiekt” jest tymczasowy, ale nadal jest wartością i jako taki można go złapać przez odniesienie.

Jakiś koleś programisty
źródło