Łączenie dwóch wektorów std ::

687

Jak połączyć dwa std::vectors?

emlai
źródło
5
Podane odpowiedzi w rzeczywistości nie łączą się. Dołączają kopię. Może być użyteczne (z punktu widzenia wydajności) utworzenie metody konkatenacji std :: vector, jednak wymagałoby to wyrafinowanego współdzielenia zarządzania węzłami i prawdopodobnie dlatego tego nie zrobiono.
FauChristian
8
@FauChristian: Nie, może nie być zastosowania z punktu widzenia wydajności. Pamięć wektorowa musi być ciągła, więc sugerowane przez ciebie jest niemożliwe. Gdybyś chciał „wyrafinowanego współdzielenia zarządzania węzłami” i gdybyś w taki sposób zmienił klasę wektorów, skończyłoby się to deque. Nawet wtedy bardzo trudno jest ponownie wykorzystać pamięć w sugerowany sposób, chociaż zacząłby być nieco bardziej wykonalny. Nie sądzę, że jest obecnie zaimplementowany. Najważniejsze jest to, że w takim współużytkowaniu węzłów zarządzania (deque) węzeł końcowy może być częściowo pusty.
Cookie
4
@lecaruyer Zdajesz sobie sprawę, że właśnie zaznaczyłeś pytanie zadane dwa lata wcześniej jako duplikat
eshirima
9
Czy tylko ja zastanawiam się, dlaczego nie jest to zaimplementowane jako a + blub a.concat(b)w standardowej bibliotece? Być może domyślna implementacja byłaby nieoptymalna, ale każda konkatenacja macierzy nie musi być mikrooptymalizowana
oseiskar
9
lata ewolucji, najbardziej zaawansowane przeciążanie operatorów ze wszystkich języków głównego nurtu, system szablonów podwajający złożoność języka, a jednak odpowiedź nie brzmi v = v1 + v2;
Spike0xff

Odpowiedzi:

727
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
Robert Gamble
źródło
53
Dodałbym tylko kod, aby najpierw uzyskać liczbę elementów, które zawiera każdy wektor, i ustawić wektor1 jako największy. W przeciwnym razie robisz dużo niepotrzebnego kopiowania.
Joe Pineda
34
Mam pytanie. Czy to zadziała, jeśli wektor1 i wektor2 są tymi samymi wektorami?
Alexander Rafferty,
6
Jeśli łączysz kilka wektorów w jeden, czy pomocne jest reservenajpierw wywołanie wektora docelowego?
Faheem Mitha
33
@AlexanderRafferty: Tylko jeśli vector1.capacity() >= 2 * vector1.size(). Co jest nietypowe, chyba że zadzwoniłeś std::vector::reserve(). W przeciwnym razie wektor przeniesie się ponownie, unieważniając iteratory przekazane jako parametry 2 i 3.
Drew Dormann
28
Szkoda, że ​​w standardowej bibliotece nie ma bardziej zwięzłego wyrażenia. .concatlub +=coś w tym stylu
nmr
193

Jeśli używasz C ++ 11 i chcesz przenieść elementy, a nie tylko je kopiować, możesz użyć std::move_iteratorwraz z wstawką (lub kopią):

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<int> dest{1,2,3,4,5};
  std::vector<int> src{6,7,8,9,10};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  // Print out concatenated vector.
  std::copy(
      dest.begin(),
      dest.end(),
      std::ostream_iterator<int>(std::cout, "\n")
    );

  return 0;
}

Nie będzie to bardziej wydajne w przykładzie z ints, ponieważ przenoszenie ich nie jest bardziej wydajne niż ich kopiowanie, ale w przypadku struktury danych ze zoptymalizowanymi ruchami można uniknąć kopiowania niepotrzebnego stanu:

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
  std::vector<std::vector<int>> src{{6,7,8,9,10}};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  return 0;
}

Po przeniesieniu element src pozostaje w nieokreślonym, ale bezpiecznym stanie do zniszczenia, a jego poprzednie elementy zostały przeniesione bezpośrednio do nowego elementu dest na końcu.

Alex
źródło
6
Metoda std :: make_move_iterator () pomogła mi przy próbie połączenia std :: wektorów std :: unique_ptr.
Knitschi,
Jaka jest różnica między tym a std::move(src.begin(), src.end(), back_inserter(dest))?
kshenoy
145

Chciałbym użyć funkcji wstawiania , na przykład:

vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
Tom Ritter
źródło
77

Lub możesz użyć:

std::copy(source.begin(), source.end(), std::back_inserter(destination));

Ten wzór jest przydatny, jeśli dwa wektory nie zawierają dokładnie tego samego rodzaju rzeczy, ponieważ można użyć czegoś zamiast std :: back_inserter do konwersji z jednego typu na drugi.

Roger Lipscombe
źródło
7
metoda kopiowania nie jest tak dobrym sposobem. Będzie wywoływał push_back wiele razy, co oznacza, że ​​jeśli trzeba wstawić wiele elementów, może to oznaczać wiele realokacji. lepiej jest użyć wstawki, ponieważ implementacja wektorowa mogłaby przeprowadzić pewną optymalizację, aby uniknąć realokacji. może zarezerwować pamięć przed rozpoczęciem kopiowania
Yogesh Arora
7
@Yogesh: przyznane, ale nic nie stoi na przeszkodzie, aby reservenajpierw zadzwonić . Przyczyna std::copyjest czasami przydatna, jeśli chcesz użyć czegoś innego niż back_inserter.
Roger Lipscombe
Kiedy mówisz „wiele przydziałów”, to prawda - ale liczba przydziałów jest najgorsza w dzienniku (liczba dodanych wpisów) - co oznacza, że ​​koszt dodania wpisu jest stały w liczbie dodanych wpisów. (Zasadniczo nie przejmuj się tym, chyba że profilowanie pokaże, że potrzebujesz rezerwy).
Martin Bonner wspiera Monikę
Zamiast tego możesz użyć std :: transform.
Martin Broadhurst,
1
kopia jest do bani, nawet z rezerwą. vector :: insert uniknie wszystkich kontroli: quick-bench.com/bLJO4OfkAzMcWia7Pa80ynwmAIA
Denis Yaroshevskiy
63

W C ++ 11 wolałbym, aby dołączyć wektor b do a:

std::move(b.begin(), b.end(), std::back_inserter(a));

kiedy ai bnie pokrywają się i bnie będą już używane.


To jest std::movez <algorithm>, nie zwykle std::move z <utility>.

Deqing
źródło
10
Nieokreślone zachowanie, jeśli rzeczywiście jest b (co jest OK, jeśli wiesz, że to nigdy nie może się zdarzyć - ale warto pamiętać o kodzie ogólnego przeznaczenia).
Martin Bonner wspiera Monikę
1
@MartinBonner Dzięki, że o tym wspomniałeś. Prawdopodobnie powinienem wrócić do starej, insertbezpieczniejszej drogi.
Deqing
15
Ach, INNE std :: move. Całkiem mylące za pierwszym razem, gdy to widzisz.
xaxxon
1
Czy ta różni się od insert()ze move_iterators? Jeśli tak to jak?
GPhilo,
1
Dodałem notatkę o tym, o czym std::movetu mówimy, ponieważ większość ludzi nie zna tego przeciążenia. Mam nadzieję, że to poprawa.
YSC
38
std::vector<int> first;
std::vector<int> second;

first.insert(first.end(), second.begin(), second.end());
James Curran
źródło
24

Wolę taki, który jest już wspomniany:

a.insert(a.end(), b.begin(), b.end());

Ale jeśli używasz C ++ 11, istnieje jeszcze jeden ogólny sposób:

a.insert(std::end(a), std::begin(b), std::end(b));

Również nie stanowi części pytania, ale zaleca się użycie reserveprzed dołączeniem w celu uzyskania lepszej wydajności. A jeśli konkatenujesz wektor ze sobą, bez rezerwowania go zawodzi, więc zawsze powinieneś reserve.


Więc w zasadzie to, czego potrzebujesz:

template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
    a.reserve(a.size() + b.size());
    a.insert(a.end(), b.begin(), b.end());
}
ST3
źródło
2
std::wynika z wyszukiwania zależnego od argumentu . end(a)to wystarczy.
Asu
4
@Asu ADL doda tylko, std::jeśli typ apochodzi od std, co eliminuje aspekt ogólny.
Potatoswatter
Słuszna uwaga. w tym przypadku jest to wektor, więc i tak by działało, ale tak, to lepsze rozwiązanie.
Asu
std :: begin () / end () zostały dodane do kolekcji (takich jak tablice), które nie mają ich jako funkcji składowych. Ale tablice również nie mają funkcji członka insert () i wywołuje pytanie „Czy istnieje kolekcja z insertem (), ale bez begin () (która działa ze std :: begin ())?”
James Curran
15

Z zasięgiem v3 możesz mieć leniwą konkatenację:

ranges::view::concat(v1, v2)

Demo .

Jarod42
źródło
12

Powinieneś użyć vector :: insert

v1.insert(v1.end(), v2.begin(), v2.end());
Boris
źródło
3
Czy to nie to samo z odpowiedzią udzieloną przez Toma Rittera i Roberta Gamble w 2008 roku?
IgNite
9

Ogólny wzrost wydajności dla Złącz jest sprawdzenie rozmiaru wektorów. I scal / wstaw mniejszy z większym.

//vector<int> v1,v2;
if(v1.size()>v2.size()) {
    v1.insert(v1.end(),v2.begin(),v2.end());
} else {
    v2.insert(v2.end(),v1.begin(),v1.end());
}
Vikramjit Roy
źródło
Tak proste, ale nigdy tak o tym nie myślałem!
Zimano,
2
Przykładowy kod jest niepoprawny. v1.insert(v2.end()...używa iteratora v2do określenia pozycji w v1.
David Stone
Możesz także użyć szybkiej zamiany. @DavidStone Zredagowałem go, aby kolejność konkat mogła zostać zmieniona. Czy można dodać początek wektora?
qwr
Możesz wstawić na początku, ale będzie wolniej. Jednak aby naprawdę „połączyć”, kolejność zazwyczaj ma znaczenie, więc właśnie to musisz zrobić.
David Stone,
7

Jeśli chcesz mieć możliwość zwięzłego łączenia wektorów, możesz przeciążyć +=operatora.

template <typename T>
std::vector<T>& operator +=(std::vector<T>& vector1, const std::vector<T>& vector2) {
    vector1.insert(vector1.end(), vector2.begin(), vector2.end());
    return vector1;
}

Następnie możesz to tak nazwać:

vector1 += vector2;
Daniel Giger
źródło
6

Jeśli interesuje Cię silna gwarancja wyjątku (gdy konstruktor kopii może zgłosić wyjątek):

template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
{
    const auto orig_v1_size = v1.size();
    v1.reserve(orig_v1_size + v2.size());
    try
    {
        v1.insert(v1.end(), v2.begin(), v2.end());
    }
    catch(...)
    {
        v1.erase(v1.begin() + orig_v1_size, v1.end());
        throw;
    }
}

Podobne append_movez silną gwarancją nie może być ogólnie zaimplementowane, jeśli konstruktor ruchu elementu wektorowego może rzucać (co jest mało prawdopodobne, ale nadal).

AlexT
źródło
Czy nie można v1.erase(...też rzucać?
Szkielet klasy,
insertjuż to obsługuje. Również to wywołanie erasejest równoważne z resize.
Potatoswatter
Lubię to - dzięki!
natersoz
5

Dodaj ten do pliku nagłówka:

template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
    vector<T> ret = vector<T>();
    copy(a.begin(), a.end(), back_inserter(ret));
    copy(b.begin(), b.end(), back_inserter(ret));
    return ret;
}

i użyj tego w ten sposób:

vector<int> a = vector<int>();
vector<int> b = vector<int>();

a.push_back(1);
a.push_back(2);
b.push_back(62);

vector<int> r = concat(a, b);

r będzie zawierać [1,2,62]

Stepan Jakowenko
źródło
Nie wiem, dlaczego zostało to odrzucone. Może nie być to najbardziej efektywny sposób, ale nie jest zły i skuteczny.
leeor_net
4

Oto rozwiązanie ogólnego zastosowania wykorzystujące semantykę przenoszenia C ++ 11:

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
    if (lhs.empty()) return rhs;
    if (rhs.empty()) return lhs;
    std::vector<T> result {};
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.cend(), lhs.cbegin(), lhs.cend());
    result.insert(result.cend(), rhs.cbegin(), rhs.cend());
    return result;
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
    lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
    return std::move(lhs);
}

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
    rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
    return std::move(rhs);
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
    if (lhs.empty()) return std::move(rhs);
    lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
    return std::move(lhs);
}

Zauważ, że różni się to od appending do a vector.

Daniel
źródło
4

Możesz przygotować własny szablon dla operatora +:

template <typename T> 
inline T operator+(const T & a, const T & b)
{
    T res = a;
    res.insert(res.end(), b.begin(), b.end());
    return res;
}

Następna rzecz - wystarczy użyć +:

vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
    cout << x << " ";
cout << endl;

Ten przykład podaje dane wyjściowe:

1 2 3 4 5 6 7 8
Vladimir U.
źródło
3
Używanie T operator+(const T & a, const T & b)jest niebezpieczne, lepiej jest używać vector<T> operator+(const vector<T> & a, const vector<T> & b).
Matthieu H,
4

Istnieje algorytm std::mergez C ++ 17 , który jest bardzo łatwy w użyciu,

Poniżej znajduje się przykład:

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    //DATA
    std::vector<int> v1{2,4,6,8};
    std::vector<int> v2{12,14,16,18};

    //MERGE
    std::vector<int> dst;
    std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));

    //PRINT
    for(auto item:dst)
        std::cout<<item<<" ";

    return 0;
}
Pavan Chandaka
źródło
3
Nie sądzę, żeby było to łatwiejsze w użyciu niż std::vector::insert, ale robi coś innego: łączenie dwóch zakresów w nowy zakres vs wstawianie jednego wektora na końcu innego. Warto wspomnieć w odpowiedzi?
jb
4

Jeśli Twoim celem jest po prostu iteracja w zakresie wartości do celów tylko do odczytu, alternatywą jest zawinięcie obu wektorów wokół proxy (O (1)) zamiast kopiowania ich (O (n)), aby były natychmiast widoczne jako pojedynczy, ciągły.

std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };

VecProxy<int> AB(A, B);  // ----> O(1)!

for (size_t i = 0; i < AB.size(); i++)
    std::cout << AB[i] << " ";  // ----> 1 2 3 4 5 10 20 30

Więcej informacji, w tym implementację „VecProxy” oraz zalety i wady, można znaleźć na stronie https://stackoverflow.com/a/55838758/2379625 .

Ronald Souza
źródło
3
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
instancja
źródło
6
Ten fragment kodu może rozwiązać problem, ale nie wyjaśnia, dlaczego ani w jaki sposób odpowiada na pytanie. Dołącz wyjaśnienie swojego kodu , ponieważ to naprawdę pomaga poprawić jakość Twojego postu. Osoby zgłaszające / recenzenci: w przypadku odpowiedzi zawierających tylko kod, takich jak ta, głosuj, nie usuwaj! (Uwaga: ta odpowiedź może być w rzeczywistości wystarczająco prosta, aby stanowić wyjaśnienie, a zatem głosować negatywnie, niepotrzebne. Możesz nadal dodać wyjaśnienie, aby zapobiec większej liczbie flag NAA / VLQ.)
Scott Weldon,
2

Zaimplementowałem tę funkcję, która łączy dowolną liczbę kontenerów, przechodząc od referencji do wartości i kopiując w inny sposób

namespace internal {

// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template<typename Target, typename Head, typename... Tail>
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
    // Currently, require each homogenous inputs. If there is demand, we could probably implement a
    // version that outputs a vector whose value_type is the common_type of all the containers
    // passed to it, and call it ConvertingConcatenate.
    static_assert(
            std::is_same_v<
                    typename std::decay_t<Target>::value_type,
                    typename std::decay_t<Head>::value_type>,
            "Concatenate requires each container passed to it to have the same value_type");
    if constexpr (std::is_lvalue_reference_v<Head>) {
        std::copy(head.begin(), head.end(), std::back_inserter(*target));
    } else {
        std::move(head.begin(), head.end(), std::back_inserter(*target));
    }
    if constexpr (sizeof...(Tail) > 0) {
        AppendNoReserve(target, std::forward<Tail>(tail)...);
    }
}

template<typename Head, typename... Tail>
size_t TotalSize(const Head& head, const Tail&... tail) {
    if constexpr (sizeof...(Tail) > 0) {
        return head.size() + TotalSize(tail...);
    } else {
        return head.size();
    }
}

}  // namespace internal

/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template<typename Head, typename... Tail>
auto Concatenate(Head&& head, Tail&&... tail) {
    size_t totalSize = internal::TotalSize(head, tail...);
    std::vector<typename std::decay_t<Head>::value_type> result;
    result.reserve(totalSize);
    internal::AppendNoReserve(&result, std::forward<Head>(head), std::forward<Tail>(tail)...);
    return result;
}
Rysował
źródło
1

Jeśli to, czego szukasz, to sposób na dołączenie wektora do innego po utworzeniu, vector::insertto najlepiej postawić zakład, na co kilkakrotnie odpowiadano, na przykład:

vector<int> first = {13};
const vector<int> second = {42};

first.insert(first.end(), second.cbegin(), second.cend());

Niestety nie ma sposobu, aby zbudować const vector<int>, ponieważ powyżej musisz zbudować, a następnie insert.


Jeśli to, czego tak naprawdę szukasz, to pojemnik do połączenia tych dwóch vector<int>s, może być dla ciebie coś lepszego, jeśli:

  1. Twój vectorzawiera prymitywy
  2. Zawarte operacje podstawowe mają rozmiar 32-bitowy lub mniejszy
  3. Chcesz constpojemnik

Jeśli wszystkie powyższe są prawdziwe, sugeruję użycie basic_stringkto char_typepasuje do rozmiaru pierwotnej zawartej w twoim vector. static_assertAby sprawdzić, czy te rozmiary są spójne, należy wprowadzić w kodzie a:

static_assert(sizeof(char32_t) == sizeof(int));

Dzięki temu utrzymaniu prawdy możesz po prostu:

const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());

Aby uzyskać więcej informacji na temat różnic między stringi vectormożna zajrzeć tutaj: https://stackoverflow.com/a/35558008/2642059

Przykład tego kodu na żywo można znaleźć tutaj: http://ideone.com/7Iww3I

Jonathan Mee
źródło
0

To rozwiązanie może być nieco skomplikowane, ale boost-rangema też kilka innych fajnych rzeczy do zaoferowania.

#include <iostream>
#include <vector>
#include <boost/range/algorithm/copy.hpp>

int main(int, char**) {
    std::vector<int> a = { 1,2,3 };
    std::vector<int> b = { 4,5,6 };
    boost::copy(b, std::back_inserter(a));
    for (auto& iter : a) {
        std::cout << iter << " ";
    }
    return EXIT_SUCCESS;
}

Często intencją jest połączenie wektora ai bpo prostu iteracja nad nim wykonując jakąś operację. W tym przypadku istnieje śmieszna prosta joinfunkcja.

#include <iostream>
#include <vector>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/copy.hpp>

int main(int, char**) {
    std::vector<int> a = { 1,2,3 };
    std::vector<int> b = { 4,5,6 };
    std::vector<int> c = { 7,8,9 };
    // Just creates an iterator
    for (auto& iter : boost::join(a, boost::join(b, c))) {
        std::cout << iter << " ";
    }
    std::cout << "\n";
    // Can also be used to create a copy
    std::vector<int> d;
    boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
    for (auto& iter : d) {
        std::cout << iter << " ";
    }
    return EXIT_SUCCESS;
}

W przypadku dużych wektorów może to być zaletą, ponieważ nie ma możliwości kopiowania. Można go również wykorzystać do łatwego kopiowania uogólnień do więcej niż jednego kontenera.

Z jakiegoś powodu nie ma czegoś takiego boost::join(a,b,c), co może być rozsądne.

Aleph0
źródło
0

Możesz to zrobić za pomocą wstępnie zaimplementowanych algorytmów STL, używając szablonu do zastosowania typu polimorficznego.

#include <iostream>
#include <vector>
#include <algorithm>

template<typename T>

void concat(std::vector<T>& valuesa, std::vector<T>& valuesb){

     for_each(valuesb.begin(), valuesb.end(), [&](int value){ valuesa.push_back(value);});
}

int main()
{
    std::vector<int> values_p={1,2,3,4,5};
    std::vector<int> values_s={6,7};

   concat(values_p, values_s);

    for(auto& it : values_p){

        std::cout<<it<<std::endl;
    }

    return 0;
}

Możesz usunąć drugi wektor, jeśli nie chcesz go dalej używać ( clear()metoda).

rekkalmd
źródło
-1

Połącz dwa std::vector-sz forpętlą w jednymstd::vector .

Przykład:

std::vector <int> v1 {1, 2, 3};//declare vector1
std::vector <int> v2 {4, 5};//declare vector2
std::vector <int> suma;//declare vector suma

for(auto i = 0; i < v1.size()-1;i++)//for loop 1
{
     suma.push_back(v1[i]);
}

for(auto i = 0; i< v2.size()-1;i++)/for loop 2
{
     suma.push_back(v2[i]);
}

for(auto i = 0; i < suma.size(); i++)//for loop 3-output
{
     std::cout<<suma[i];
}

Wpisz ten kod w main().

GobeRadJem32
źródło
Ci forpętle są błędne. Prawidłowe indeksy w wektorze wynoszą od 0 do size()-1. Musisz zakończyć warunki zakończenia pętli i < v1.size(), używając <nie <=. Zastosowanie złego stanu powoduje dostęp do pamięci poza kontenerem.
Blastfurnace
poza tym nie działa, ten kod jest w dużej mierze nie idiomatyczny. Powinieneś przynajmniej używać autoiteratorów zamiast ręcznego indeksowania. Nie obchodzi Cię, jaki indeks łączysz, tylko że jest on wykonywany sekwencyjnie.
Tarick Welling
Czy możesz wyjaśnić, dlaczego używasz size()-1w dwóch warunkach pętli? To pomija ostatnie elementy wektorowe. Trzecia pętla jest teraz jedyną poprawną.
Blastfurnace
-3

Szczerze mówiąc, możesz szybko połączyć dwa wektory, kopiując elementy z dwóch wektorów do drugiego lub po prostu dołączając jeden z dwóch wektorów !. To zależy od twojego celu.

Metoda 1: Przypisz nowy wektor, którego rozmiar jest sumą rozmiaru dwóch oryginalnych wektorów.

vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector

Metoda 2: Dołącz wektor A, dodając / wstawiając elementy wektora B.

// Loop for insert elements of vector_B into vector_A with insert() 
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());
nvnhcmus
źródło
4
Co dodaje twoja odpowiedź, której jeszcze nie podano w innych odpowiedziach?
Mat
13
@Mat: pogrubione znaki.
marcv81
Jeśli oryginalne wektor (y) nie są już potrzebne, może być lepiej użyć std::move_iterator, aby elementy były przenoszone zamiast kopiowane. (patrz en.cppreference.com/w/cpp/iterator/move_iterator ).
tmlen
Co to jest setcapacity? Co to jest function: ?
LF
@LF Myślę, że mówi o resizemetodzie.
Matthieu H,