С++ STL copy() безопасность исключений
Если я делаю
std::copy(source, source + size, destination);
Есть ли у меня надежная гарантия безопасности? То есть если std:: copy throws, назначение остается неизменным?
Ответы
Ответ 1
Из стандарта:
25.3.1 Копирование [alg.copy]
template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
1 Эффекты: копирует элементы в диапазоне [first,last)
в диапазон [result,result + (last -first))
начиная с first
и переходя к last
. Для каждого неотрицательного целого n < (last -first)
выполняется *(result + n) = *(first + n)
.
2 Возвращает: result + (last - first).
3 Требуется: result
не должно находиться в диапазоне [first,last)
.
4 Сложность: точно last - first
назначения.
Он не гарантирует никаких гарантий безопасности исключений. В нем также не указывается, каково будет поведение, если result
находится в диапазоне [first,last)
.
Ответ 2
Приложение E: Безопасность исключений стандартной библиотеки из Stroustrop Язык программирования С++ свободно доступен для просмотра с его сайта.
Из этого:
Алгоритм copy() (§18.6.1) не предлагает сильного гарантия безопасности исключения. Это не гарантирует, что он оставит свою цель без изменений, если исключение бросается во время копирования
Ответ 3
Быстрый поиск по разделу 25 (предложение, определяющее большинство стандартных алгоритмов) показывает, что нет экземпляра фразы без эффектов, а стандарт определяет сильную защиту исключений как "если выбрано исключение (есть/функция имеет ) никаких эффектов". Другими словами, ничто в пункте 25 не содержит надежной гарантии безопасности.
Кроме того, как std::copy
может предложить сильную гарантию безопасности исключений? dest
может быть произвольным выходным итератором, который не обязательно читается и может выполнять произвольные операции над записью. Что, если это std::ostream_iterator
- как вы "не записываете" то, что было записано в поток?
Ответ 4
Копия определена в 25.3.1 как
template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
1 Effects: Copies elements in the range [first,last) into the range [result,result + (last -
first)) starting from first and proceeding to last. For each non-negative integer n < (last -
first), performs *(result + n) = *(first + n).
2 Returns: result + (last - first).
3 Requires: result shall not be in the range [first,last).
4 Complexity: Exactly last - first assignments.
Что может быть эффективно записано как:
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = *first;
++result; ++first;
}
return result;
}
Способ форматирования, если исключение происходит в любое время после первого выполнения цикла, тогда пункт назначения будет изменен.