Обычно это не следует делать с std::copy_n
, что предполагает, что предоставленный итератор при увеличении n раз остается действительным:
Копирует ровно count
значений из диапазона, начинающегося с first
, до диапазона, начинающегося с result
. Формально для каждого неотрицательного целого числа i < n
выполняется *(result + i) = *(first + i)
.
( cppreference.com статья на std::copy_n
)
Если вы можете гарантировать это, то хорошо, но обычно с std::cin
это невозможно. Вы можете легко разыменовать недействительный итератор:
Построенный по умолчанию std::istream_iterator
известен как итератор конца потока. Когда действительный std::istream_iterator
достигает конца основного потока, он становится равным итератору конца потока. Разыменование или его приращение в дальнейшем вызывает неопределенное поведение.
( cppreference.com статья в std::istream_iterator
)
Вы в значительной степени находитесь там с вашим циклом, хотя я бы, вероятно, использовал более сильное условие завершения, чтобы избежать лишних чтений из "мертвого" потока:
vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
if (!cin >> v[i])
break;
На самом деле я бы соблазнился обернуть это во что-то вроде std::copy_n
, но принимает полный «диапазон», границы которого могут быть проверены в дополнение к подсчету от 0 до N .
Реализация может выглядеть следующим образом:
template<class InputIt, class Size, class OutputIt>
OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
{
for (Size i = 0; i < count && first != last; ++i)
*result++ = *first++;
return result;
}
Вы бы использовали это так:
copy_atmost_n(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
N,
std::back_inserter(v)
);
Теперь вы получаете M элементов, где M - это либо количество предоставленных входов, либо N , в зависимости от того, что меньше.