Если я делаю
std::copy(source, source + size, destination);
Есть ли у меня надежная гарантия безопасности? То есть если std:: copy throws, назначение остается неизменным?
Если я делаю
std::copy(source, source + size, destination);
Есть ли у меня надежная гарантия безопасности? То есть если std:: copy throws, назначение остается неизменным?
Из стандарта:
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)
.
Приложение E: Безопасность исключений стандартной библиотеки из Stroustrop Язык программирования С++ свободно доступен для просмотра с его сайта.
Из этого:
Алгоритм copy() (§18.6.1) не предлагает сильного гарантия безопасности исключения. Это не гарантирует, что он оставит свою цель без изменений, если исключение бросается во время копирования
Быстрый поиск по разделу 25 (предложение, определяющее большинство стандартных алгоритмов) показывает, что нет экземпляра фразы без эффектов, а стандарт определяет сильную защиту исключений как "если выбрано исключение (есть/функция имеет ) никаких эффектов". Другими словами, ничто в пункте 25 не содержит надежной гарантии безопасности.
Кроме того, как std::copy
может предложить сильную гарантию безопасности исключений? dest
может быть произвольным выходным итератором, который не обязательно читается и может выполнять произвольные операции над записью. Что, если это std::ostream_iterator
- как вы "не записываете" то, что было записано в поток?
Копия определена в 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;
}
Способ форматирования, если исключение происходит в любое время после первого выполнения цикла, тогда пункт назначения будет изменен.