1016 Stimmen

Verkettung von zwei std::Vektoren

Wie verkette ich zwei std::vector s?

10 Stimmen

Die gegebenen Antworten sind nicht wirklich zusammenhängend. Sie fügen eine Kopie an. Es könnte (aus Gründen der Effizienz) sinnvoll sein, eine std::vector concatenate-Methode zu erstellen, allerdings würde dies eine ausgeklügelte gemeinsame Nutzung der Verwaltung der Knoten erfordern, und das ist wahrscheinlich der Grund, warum dies noch nicht geschehen ist.

16 Stimmen

@FauChristian: Nein, unter Effizienzgesichtspunkten kann es keinen Nutzen geben. Der Vektorspeicher muss kontinuierlich sein, also ist das, was Sie vorschlagen, unmöglich. Wenn Sie "eine ausgeklügelte gemeinsame Nutzung der Verwaltung der Knoten" wollten und die Vektorklasse auf diese Weise ändern würden, würden Sie bei einer Deque landen. Selbst dann ist es sehr schwierig, den Speicher in der vorgeschlagenen Weise wiederzuverwenden, auch wenn es allmählich ein wenig praktikabler wäre. Ich glaube nicht, dass es derzeit implementiert ist. Die Hauptsache ist, dass in einem solchen Sharing von Management-Knoten (eine deque) der Endknoten teilweise leer sein könnte.

18 Stimmen

Bin ich der Einzige, der sich fragt, warum dies nicht als a + b o a.concat(b) in der Standardbibliothek? Vielleicht wäre die Standardimplementierung suboptimal, aber nicht jede Array-Verkettung muss mikro-optimiert sein

16voto

Daniel Giger Punkte 1199

Wenn Sie in der Lage sein wollen, Vektoren prägnant zu verketten, können Sie die += Betreiber.

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;
}

Dann können Sie es so nennen:

vector1 += vector2;

0 Stimmen

Dies kann sehr verwirrend sein und wird nicht empfohlen. += könnte als eine Änderung wahrgenommen werden Elementweise .

0 Stimmen

Dies ist keine gute Idee, da der Operator von ADL nicht gefunden wird, da beide Argumente aus dem Namespace std . Das bedeutet, dass die Symbole entweder im globalen Namespace definiert/gezogen werden müssen, um entdeckt zu werden, oder im selben Namespace wie jeder Code, der sie verwendet. Nicht wirklich ideal über nur eine benannte Funktion, die keine dieser Probleme hat.

10voto

Boris Punkte 318

Sie sollten Folgendes verwenden vector::insert

v1.insert(v1.end(), v2.begin(), v2.end());

16 Stimmen

Ist dies nicht die gleiche Antwort wie die von Tom Ritter und Robert Gamble im Jahr 2008?

9voto

AlexT Punkte 1383

Wenn Sie an einer starken Ausnahmegarantie interessiert sind (wenn der Kopierkonstruktor eine Ausnahme auslösen kann):

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;
    }
}

Ähnlich append_move mit starker Garantie kann im Allgemeinen nicht implementiert werden, wenn der Move-Konstruktor des Vektorelements einen Throw auslösen kann (was unwahrscheinlich ist, aber dennoch).

0 Stimmen

Ist es nicht möglich, dass v1.erase(... zu werfen?

2 Stimmen

insert übernimmt dies bereits. Außerdem ist der Aufruf von erase ist gleichbedeutend mit einer resize .

8voto

Ronald Souza Punkte 514

Wenn Ihr Ziel ist es einfach, über den Bereich der Werte für Nur-Lese-Zwecke zu iterieren, ist eine Alternative zu wickeln beide Vektoren um einen Proxy (O (1)) statt Kopieren von ihnen (O (n)), so dass sie sofort als eine einzige, zusammenhängende gesehen werden.

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

Siehe https://stackoverflow.com/a/55838758/2379625 für weitere Einzelheiten, einschließlich der 'VecProxy'-Implementierung sowie der Vor- und Nachteile.

6voto

Stepan Yakovenko Punkte 7499

Fügen Sie diese in Ihre Header-Datei ein:

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;
}

und verwenden Sie es auf diese Weise:

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 wird [1,2,62] enthalten

0 Stimmen

Ich weiß nicht, warum dies heruntergestuft wurde. Es ist vielleicht nicht die effizienteste Art, dies zu tun, aber es ist nicht falsch und effektiv.

0 Stimmen

Und es funktioniert, wenn Sie den gleichen Vektor in als beide Parameter übergeben, um einen Vektor mit sich selbst zu verketten.

4 Stimmen

@leeo non const ref args for one

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X