Это безопасно*. Почему? Потому что стандарт не говорит, что это небезопасно. Они копируют функции из 25.3.1 и имеют Требования: для вещей, которые им требуются (именно здесь указывается перекрывающийся запрет в других формах копирования).
Однако copy_n
не говорит, что требует, чтобы диапазоны не перекрывались, что означает, что это нормально, так как это не запрещено явно. Если бы это требовалось, оно бы заявило об этом.
*Редактировать: Когда я имел в виду «безопасный», я имел в виду, что это не неопределенное поведение или неправильно сформированная программа. Однако не гарантируется, что результаты будут такими, как вы, вероятно, предполагали, если диапазоны памяти перекрываются. Единственное, что мы гарантируем, это:
- Для каждого неотрицательного целого числа
i < n
, *(result + i) = *(first + i)
выполняется
- Вызов функции с перекрывающимися диапазонами не запрещен и не приводит к неопределенному поведению.
Таким образом, мы можем сделать вывод, что если диапазоны перекрываются, то результаты, хранящиеся в месте назначения, больше не гарантируются как точная (по порядку) копия источника. Мы гарантируем, что каждое значение в месте назначения будет получено из источника, хотя точное значение этих значений зависит от перекрытия и точного порядка, в котором копируются элементы.
Итак, если под «безопасным» вы подразумеваете, что пункт назначения всегда имеет точную копию источника (например, memmove
), то нет, это не «безопасно». Но это безопасно в том смысле, что само по себе не вызовет неопределенного/недопустимого поведения.
Напомним, что мы гарантируем, что *(result + i) = *(first + i)
будет выполнено для каждого элемента во всем диапазоне. Мы гарантируем, что если диапазоны перекрываются, программа все равно не является неопределенной. Нам не гарантируется порядок, в котором копируются элементы. Мы не гарантируем, что если диапазоны перекрываются, какими будут точные значения, хранящиеся в результате (но мы знаем, что все они получены из источника).
person
Cornstalks
schedule
23.12.2013
copy_n
в MSVC++, по-видимому, делегируетstd::memmove
. Обратите внимание, что мы делаем это только в том случае, если такое преобразование правильно; то есть, где итераторы являются указателями на легко копируемые объекты. - person James McNellis   schedule 23.12.2013std::list
, это было бы небезопасно для реализации MSVC++. Звучит как ответ мне... - person Billy ONeal   schedule 23.12.2013copy_n
. Не понимаю, почему этого нет в стандарте. Вы можете отправить вопрос. Кстати,copy
запрещает перекрытие только в том случае, если вывод начинается во входном диапазоне, но работает нормально, когда выходной диапазон заканчивается во входном диапазоне (т. е. копирование влево). - person TemplateRex   schedule 04.01.2014