Мне нужно скопировать std::set
в std::vector
:
std::set <double> input;
input.insert(5);
input.insert(6);
std::vector <double> output;
std::copy(input.begin(), input.end(), output.begin()); //Error: Vector iterator not dereferencable
В чем проблема?
assign()
функция:output.assign(input.begin(), input.end());
Ответы:
Вам необходимо использовать
back_inserter
:std::copy
не добавляет элементы в контейнер, в который вы вставляете: он не может; в контейнере есть только итератор. Из-за этого, если вы передаете выходной итератор напрямуюstd::copy
, вы должны убедиться, что он указывает на диапазон, по крайней мере достаточно большой, чтобы содержать входной диапазон.std::back_inserter
создает выходной итератор, который вызываетpush_back
контейнер для каждого элемента, поэтому каждый элемент вставляется в контейнер. В качестве альтернативы, вы могли бы создать достаточное количество элементов в,std::vector
чтобы содержать копируемый диапазон:Или вы можете использовать
std::vector
конструктор диапазона:источник
output.insert(output.end(), input.begin(), input.end());
вместо этого?output.insert(output.cend(), input.cbegin(), input.cend());
что вы думаете? Спасибо.input,size()
пустых записей и затем добавляете добавления после этого. Я думаю, что вы хотите использоватьstd::vector<double> output; output.reserve(input.size()); std::copy(...);
.Просто используйте конструктор для вектора, который принимает итераторы:
Предполагается, что вам просто нужно содержимое s в v, и в v нет ничего до копирования данных в него.
источник
Вот еще один вариант использования
vector::assign
:источник
Вы не зарезервировали достаточно места в вашем векторном объекте для хранения содержимого вашего набора.
источник
Я думаю, что самый эффективный способ - это предварительно выделить, а затем использовать элементы:
Таким образом, мы будем вызывать конструктор копирования только для каждого элемента, а не вызывать конструктор по умолчанию, а затем копировать оператор присваивания для других решений, перечисленных выше. Больше разъяснений ниже.
back_inserter может использоваться, но он вызовет push_back () для вектора ( https://en.cppreference.com/w/cpp/iterator/back_insert_iterator ). emplace_back () более эффективен, потому что он избегает создания временного при использовании push_back () . Это не проблема с тривиально сконструированными типами, но будет влиять на производительность для нетривиально сконструированных типов (например, std :: string).
Нам нужно избегать создания вектора с аргументом размера, который приводит к созданию всех элементов по умолчанию (ни за что). Как, например, с решением с использованием std :: copy () .
И, наконец, метод vector :: assign () или конструктор, принимающий диапазон итераторов, не являются хорошими вариантами, потому что они будут вызывать std :: distance () (чтобы узнать количество элементов) на итераторах множества . Это приведет к нежелательной дополнительной итерации по всем элементам набора, поскольку набор является структурой данных дерева двоичного поиска и не реализует итераторы с произвольным доступом.
Надеюсь, это поможет.
источник
back_inserter
не нужно использоватьstd::copy
не может быть использован для вставки в пустой контейнер. Для этого вам нужно использовать insert_iterator следующим образом:источник