2008-11-24 13 views
30

Ich bin ein C/Python-Programmierer in C++ Land mit der STL zum ersten Mal arbeiten.C++ erweitern einen Vektor mit einem anderen Vektor

In Python, eine Liste mit einer anderen Liste verlauf verwendet die .extend Methode:

>>> v = [1, 2, 3] 
>>> v_prime = [4, 5, 6] 
>>> v.extend(v_prime) 
>>> print(v) 
[1, 2, 3, 4, 5, 6] 

I derzeit diesen algorithmischen Ansatz verwenden Vektoren in C zu verlängern ++:

v.resize(v.size() + v_prime.size()); 
copy(v_prime.begin(), v_prime.end(), v.rbegin()); 

Ist dies der üblicher Weg, der Vektoren erweitern, oder wenn es einen einfacheren Weg gibt, den ich vermisse?

+0

Mögliche Duplikat [verketten zwei std :: Vektoren] (http://stackoverflow.com/questions/201718/concatenating-two-stdvectors) –

Antwort

45

Von here

// reserve() is optional - just to improve performance 
v.reserve(v.size() + distance(v_prime.begin(),v_prime.end())); 
v.insert(v.end(),v_prime.begin(),v_prime.end()); 
+0

Ich glaube nicht, dass es eine Spezialisierung von vector :: insert für Direktzugriffs-Eingabe-Iteratoren gibt, wenn also die Leistung zählt, reserve() zuerst. –

+9

Sowohl VC++ 9.0 als auch GCC 4.3.2 bestimmen die Iteratorkategorie intern, sodass Sie keine Reservierung vornehmen müssen. –

+12

Ich weiß, das ist 8 Jahre alt, aber gibt es einen Grund, warum Sie 'distance()' statt einfach 'v_prime.size()' verwendet haben? – Holt

18
copy(v_prime.begin(), v_prime.end(), back_inserter(v)); 
+0

Ich denke, der Raum muss immer noch reserviert werden() - d, um die Leistung zu verbessern –

+1

+1, da der Fragesteller für "einfachste", nicht "schnellste" gebeten, so Speicherplatz reservieren (während Erwähnung als Option) ist unnötig. –

+0

Ich denke dmitry Lösung ist einfacher und schneller. upvote für diesen Typ anway :) –

1

benötigen ich zwei verschiedene Varianten der extend Funktion in C++ 14, wobei eine unterstützten Bewegung Semantik für jedes Element des Vektors angehängt werden.

vec ist Ihre v und ext ist Ihre v_prime.

/** 
* Extend a vector with elements, without destroying source one. 
*/ 
template<typename T> 
void vector_extend(std::vector<T> &vec, const std::vector<T> &ext) { 
    vec.reserve(vec.size() + ext.size()); 
    vec.insert(std::end(vec), std::begin(ext), std::end(ext)); 
} 

/** 
* Extend a vector with elements with move semantics. 
*/ 
template<typename T> 
void vector_extend(std::vector<T> &vec, std::vector<T> &&ext) { 
    if (vec.empty()) { 
     vec = std::move(ext); 
    } 
    else { 
     vec.reserve(vec.size() + ext.size()); 
     std::move(std::begin(ext), std::end(ext), std::back_inserter(vec)); 
     ext.clear(); 
    } 
} 
3

Es gibt mehrere Möglichkeiten, Ihr Ziel zu erreichen.

std :: vector :: insert

Der Vektor kann durch Einfügen von neuen Elementen vor dem Element an der angegebenen Position ausgefahren werden, effektiv die Behältergröße durch die Anzahl der Elemente eingefügt zu erhöhen. Sie können einem der folgenden Ansätze folgen. Die zweite Version verwendet C++ 11 und kann als eine allgemeinere Antwort betrachtet werden, da b auch ein Array sein könnte.

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

Manchmal ist es in der Praxis eine bewährte Methode, die Reservefunktion vor der Verwendung von std :: vector :: insert zu verwenden. Std :: vector :: reserve Funktion erhöht die Kapazität des Containers auf einen Wert, der größer oder gleich new_cap ist. Wenn new_cap größer als die aktuelle Kapazität() ist, wird neuer Speicher zugewiesen, andernfalls führt die Methode nichts aus.

a.reserve(a.size() + distance(b.begin(), b.end())); 

Die Verwendung der Reservefunktion ist nicht erforderlich, kann aber ratsam sein. Und es ist am besten, Reserve zu verwenden, wenn Sie wiederholt in einen Vektor einfügen, für den Sie die endgültige Größe kennen, und diese Größe ist groß. Andernfalls ist es besser, wenn die STL Ihren Vektor nach Bedarf wachsen lässt.

std ::

std :: copy ist die zweite Option, die Sie um Ihr Ziel zu erreichen, berücksichtigen können. Diese Funktion kopiert die Elemente im Bereich (first, last) in den Bereich ab result.

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

jedoch die Verwendung von std :: Kopie ist langsamer als die Verwendung von std :: vector :: insert(), weil std :: copy() nicht genügend Platz reservieren kann, bevor Hand (es nicht tut haben Zugriff auf den Vektor selbst, nur auf einen Iterator, der hat, während std :: vector :: insert(), eine Member-Funktion, kann. Dadurch ist std :: copy in der Tat langsamer als std :: vector :: insert. Die meisten Leute verwenden std :: copy, ohne dieses Szenario zu kennen.

boost :: push_back

Die dritte Option, die Sie betrachten können, ist der Einsatz von der Boost-push_back Funktion.

boost::push_back(a, b); 
1

Verwendung std::vector::insert;

A.reserve(A.size() + B.size()); 
A.insert(A.end(), B.begin(), B.end()); 

reserve() ist optional, aber mit ihm die Leistung zu verbessern hilft.


Convienent Code-Generator wertvolle Sekunden zu sparen:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css"><script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script><script src="https://cdn.jsdelivr.net/clipboard.js/1.6.0/clipboard.min.js"></script><script>function generateCode(){codeTemplate="{0}.reserve({0}.size() + {1}.size()); \n{0}.insert({0}.end(), {1}.begin(), {1}.end());",first=document.getElementById("1").value,second=document.getElementById("2").value,""==first&&(first="A"),""==second&&(second="B"),document.getElementById("c").innerHTML=String.format(codeTemplate,first,second)}String.format||(String.format=function(a){var b=Array.prototype.slice.call(arguments,1);return a.replace(/{(\d+)}/g,function(a,c){return"undefined"!=typeof b[c]?b[c]:a})});</script><div class="A" style="margin:3% 10% 1% 10%;"><label for="1">First vector name:</label><input id="1"/><br/><label for="1">Second vector name:</label><input id="2"/><div class="D"><a class="waves-effect waves-light btn red col" onclick="generateCode();" style="margin:0 0 4% 0;">Generate Code</a></div><textarea id="c" onclick="this.select()" style="border:none;height:auto;overflow: hidden;font-family:Consolas,Monaco;">A.reserve(A.size() + B.size());&#13;&#10;A.insert(A.end(), B.begin(), B.end());</textarea></div>

Verwandte Themen