Возврат добавленного элемента или контейнера в функциях-членах контейнера безопасным способом невозможен. Контейнеры STL в основном обеспечивают «сильную гарантию» . Возврат манипулируемого элемента или контейнера сделает невозможным предоставление сильной гарантии (это обеспечит только «базовую гарантию»). Объяснение этих условий приведено на веб-сайте Boost по адресу Исключительная безопасность в общих компонентах . См. Ниже с сайта Boost .
- Базовая гарантия : что инварианты компонента сохраняются и ресурсы не просачиваются.
- надежная гарантия : что операция либо успешно завершена, либо вызвала исключение, оставляя состояние программы точно таким, каким оно было до начала операции.
- гарантия отсутствия бросков : операция не вызовет исключение.
Вернуться к теме: Согласно этому предыдущему SO-ответу , причина этого в том, что возвращение чего-либо может вызвать конструктор копирования, который может вызвать исключение. Но функция уже вышла, поэтому она успешно выполнила свою основную задачу, но все же вызвала исключение, которое является нарушением строгой гарантии. Вы можете подумать: «Ну, тогда давайте вернемся по ссылке!» , хотя это звучит как хорошее решение, но и не совсем безопасно. Рассмотрим следующий пример:
MyClass bar = myvector.push_back(functionReturningMyClass()); // imagine push_back returns MyClass&
Тем не менее, если оператор присвоения копии генерирует ошибку, мы не знаем, был ли push_back успешным или нет, тем самым косвенно нарушая строгую гарантию. Хотя это не прямое нарушение. Конечно, использование MyClass& bar = //...
вместо этого решило бы эту проблему, но было бы весьма неудобно, чтобы контейнер мог войти в неопределенное состояние только потому, что кто-то забыл &.
Довольно похожая причина лежит в том, что std::stack::pop()
не возвращает выбранное значение. Вместо этого top(
) возвращает самое верхнее значение безопасным способом. после вызова top, даже когда выдает конструктор копирования или конструктор присвоения копии, вы все равно знаете, что стек не изменился.