Wie verkette ich zwei std::vector
s?
Dies kann sehr verwirrend sein und wird nicht empfohlen. +=
könnte als eine Änderung wahrgenommen werden Elementweise .
Wie verkette ich zwei std::vector
s?
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;
Dies kann sehr verwirrend sein und wird nicht empfohlen. +=
könnte als eine Änderung wahrgenommen werden Elementweise .
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.
Sie sollten Folgendes verwenden vector::insert
v1.insert(v1.end(), v2.begin(), v2.end());
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).
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.
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
Ich weiß nicht, warum dies heruntergestuft wurde. Es ist vielleicht nicht die effizienteste Art, dies zu tun, aber es ist nicht falsch und effektiv.
Und es funktioniert, wenn Sie den gleichen Vektor in als beide Parameter übergeben, um einen Vektor mit sich selbst zu verketten.
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.
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
oa.concat(b)
in der Standardbibliothek? Vielleicht wäre die Standardimplementierung suboptimal, aber nicht jede Array-Verkettung muss mikro-optimiert sein58 Stimmen
Jahre der Entwicklung, das fortschrittlichste Operator-Overloading aller Mainstream-Sprachen, ein Templating-System, das die Komplexität der Sprache verdoppelt, und dennoch lautet die Antwort nicht v = v1 + v2;
7 Stimmen
Ich vermute, dass die STL die Sprache nicht überspezifizieren wollte, für den Fall, dass der Operator etwas anderes tun sollte, z. B. Kraftvektoren in einem Physikmodell hinzufügen. In diesem Fall könnten Sie überladen wollen
forceVector1 + forceVector2
um in klarem, prägnantem Code punktweise zu addieren.3 Stimmen
@Spike0xff, v = v1 + v2 hat in der Mathematik eine Bedeutung, die nichts mit Verkettung zu tun hat. Es hat auch einige Anforderungen, um berechenbar zu sein. Ich würde eher eine Append-Methode vorschlagen (eine Abkürzung dessen, was man mit
insert
) oder eine Push-Back-Überlastung.