Muszę skopiować std::set
do 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
Gdzie jest problem?
assign()
funkcja:output.assign(input.begin(), input.end());
Odpowiedzi:
Musisz użyć
back_inserter
:std::copy
nie dodaje elementów do kontenera, do którego wstawiasz: nie może; ma tylko iterator do kontenera. Z tego powodu, jeśli przekazujesz iterator wyjściowy bezpośrednio dostd::copy
, musisz upewnić się, że wskazuje zakres, który jest co najmniej wystarczająco duży, aby pomieścić zakres wejściowy.std::back_inserter
tworzy iterator danych wyjściowych, który wywołujepush_back
kontener dla każdego elementu, więc każdy element jest wstawiany do kontenera. Alternatywnie możesz utworzyć wystarczającą liczbę elementów w elemencie,std::vector
aby pomieścić kopiowany zakres:Lub możesz użyć
std::vector
konstruktora zakresu:źródło
output.insert(output.end(), input.begin(), input.end());
zamiast tego?output.insert(output.cend(), input.cbegin(), input.cend());
Co o tym sądzisz? Dzięki.input,size()
pustych wpisów, a następnie dołączasz kolejne. Myślę, że masz zamiar użyćstd::vector<double> output; output.reserve(input.size()); std::copy(...);
.Po prostu użyj konstruktora dla wektora, który przyjmuje iteratory:
Zakłada, że chcesz tylko zawartość s in v, a przed skopiowaniem danych nie ma nic w v.
źródło
oto inna alternatywa użycia
vector::assign
:źródło
Nie zarezerwowałeś wystarczająco dużo miejsca w swoim obiekcie wektorowym, aby pomieścić zawartość zestawu.
źródło
Myślę, że najbardziej efektywnym sposobem jest wstępne przydzielenie, a następnie umieszczenie elementów:
W ten sposób będziemy wywoływać konstruktor kopiujący tylko dla każdego elementu, w przeciwieństwie do wywoływania najpierw konstruktora domyślnego, a następnie kopiowania operatora przypisania dla innych rozwiązań wymienionych powyżej. Więcej wyjaśnień poniżej.
Można użyć back_inserter, ale wywoła on push_back () na wektorze ( https://en.cppreference.com/w/cpp/iterator/back_insert_iterator ). embrace_back () jest bardziej wydajna, ponieważ unika tworzenia tymczasowego przy użyciu push_back () . Nie jest to problem z trywialnie skonstruowanymi typami, ale będzie implikował wydajność dla nietrywialnie skonstruowanych typów (np. Std :: string).
Musimy unikać konstruowania wektora z argumentem size, który powoduje, że wszystkie elementy są domyślnie konstruowane (za nic). Jak na przykład z rozwiązaniem używającym std :: copy () .
I wreszcie, metoda vector :: assign () lub konstruktor pobierający zakres iteratora nie są dobrymi opcjami, ponieważ będą wywoływać std :: distance () (aby poznać liczbę elementów) na iteratorach set . Spowoduje to niepożądaną dodatkową iterację przez wszystkie elementy zestawu , ponieważ zestaw jest strukturą danych Binary Search Tree i nie implementuje iteratorów dostępu swobodnego.
Mam nadzieję, że to pomoże.
źródło
back_inserter
nie trzeba go używaćstd::copy
nie można używać do wkładania do pustego pojemnika. Aby to zrobić, musisz użyć insert_iterator w następujący sposób:źródło