Вопрос: Try-catch-throw. Как понять эту схему?

Лучший ответ: Вы называете одним словом "ошибка" несколько совершенно различных вещей, не связанных между собой:Синтаксическая ошибка в исходном коде. "где в тип string вводится int и сообщается об ошибке" - это невозможно в принципе, так как ваш исходный код, в котором нарушено соответствие типов, не является валидной программой (все равно что оставить незакрытую скобку), компилятор не сможет скомпилировать из него никакой бинарный исполнимый файл просто потому, что видит бессмыслицу в таком исходнике.Исключительная ситуация (exception) во время выполнения. Она всегда предусмотрена кодером (этим она и отличается). Например я пишу функцию, которая должна делить одно число на другое, я предполагаю, что кто-то (типа меня же) может использовать эту функцию неправильно и передать ноль в качестве делителя. Я хочу, чтобы такому пользователю прилетел (по голове) exception, красноречиво сообщающий о том, что так делать не стоит. Для этого я пишу if (denominator == 0) { throw std::invalid_argument( "НЕ НАДО ТАК!" ); }. Теперь, если мне нужно выполнить какой-то кусок кода, в котором есть вызовы функций, из которых могут вылетать исключения, и я хочу как-то локализовать эту проблему и обезопасить от этого остальную программу, то я пишу try { divide(x, 0); } catch (const std::invalid_argument& e) { /* Я все понял, я так больше не буду. */ }.Undefined behavior - это результат не предусмотренной никем ситуации во время выполнения. Например, я заб(ы/и)л на то, что кто-то может передать ноль в мою функцию в качестве делителя и пишу int divide(int a, int b) { return a / b; }. И однажды это происходит, кто-то (да я же сам) передает туда ноль и... Что должно произойти в этой ситуации? Я не знаю, CPU не знает, компилятор об этом не позаботился, ОС тоже не знает, но на всякий случай она прихлопнет весь процесс целиком и (возможно) напишет в консоль что-то типа segmentation fault.
А что, если я буду вызывать такую подозрительную функцию из блока try-catch? - Да ничего это не меняет. try-catch ловит только преднамеренно брошенные исключения в ситуации, когда возможность возникновения ошибки была предусмотрена кодером. try-catch ничем не может помочь против undefined behavior потому, что предусматривать возможные ошибки во время выполнения - это задача кодера, а не компилятора, который занимается только контролем соответствия типов и формальной корректности программы.
Если вам не по душе концепция undefined behavior, то переходите на Java или .NET, там компиляторы сами добавляют все необходимые (и обходимые) проверки ценой снижения быстродействия вашей программы.

Худший ответ: Конкретно в этом случае вы можете легко проверять условным оператором, а не вышли ли вы за пределы массива. До цикла, разумеется - там быстрее будет работать.
Я бы тут не полагался бы на исключения.
Ну а конкретно про ваш случай:
С/С++ являются инструментами, в которых легко отстрелить себе ногу.
В чем вы только что и убедились.
Компилятор предполагает, что разработчик ЗНАЕТ, что делает и не проверяет никак выход за пределы массива. Вылет вы словили вообще совершенно случайно. И это везение что вы словили падение так просто и сразу. Скорее всего там был Segmentation Fault?
Это особенность С/С++ - там за все такие косяки отвечает сам программист.
Дело в том, что изначально С/С++ заточены на скорость, а постоянные проверки выхода за пределы массива (вектора) заметно замедляют работу программы во многих случаях.
Однако вы можете изменить такое поведение компилятора.Для этого вам нужно задать компилятору некие параметры.
Какие именно - не подскажу, компиляторы разные.
Но у всех мне известных компиляторов С/С++ можно указать, чтобы компилятор делал эти самые дополнительные проверки, которые вы тут ожидаете.