Schöne Möglichkeit, einen Vektor an sich selbst anzuhängen

Lesezeit: 4 Minuten

Schone Moglichkeit einen Vektor an sich selbst anzuhangen
Aman Deep Gautam

Ich möchte den Inhalt des Vektors duplizieren und am Ende des ursprünglichen Vektors anhängen, dh v[i]=v[i+n] for i=0,2,...,n-1

Ich suche nach einer netten Möglichkeit, dies zu tun, nicht mit einer Schleife. ich sah std::vector::insert aber die iterative Version verbietet es einem Iterator *this(dh Verhalten ist undefiniert).

Ich habe es auch versucht std::copy wie folgt (aber es führte zu einem Segmentierungsfehler):

copy( xx.begin(), xx.end(), xx.end());

  • mögliches Duplikat von Falsche Ergebnisse beim Anhängen von Vektor an sich selbst mit copy und back_inserter

    – Ben Voigt

    14. Juli 2013 um 5:20 Uhr

  • @BenVoigt, um fair zu sein, als ich diese Frage stellte, versuchte ich es und wollte wissen, warum es nicht funktionierte. Ich brauchte eigentlich keine elegante Arbeitslösung, daher werden in den Kommentaren nur solche erwähnt.

    – Chris

    14. Juli 2013 um 7:56 Uhr

  • Ich muss mich fragen, ob die meisten Leute die Implementierung beim ersten Mal richtig gemacht hätten, wenn sie sie mit einer Schleife codiert hätten.

    – MarkB

    16. Juli 2013 um 1:52 Uhr

1646317211 524 Schone Moglichkeit einen Vektor an sich selbst anzuhangen
Ben Voigt

Beeindruckend. So viele Antworten, die nahe beieinander liegen, keine mit den richtigen Teilen. Sie brauchen beides resize (oder reserve) und copy_nzusammen mit der Erinnerung an die Originalgröße.

auto old_count = xx.size();
xx.resize(2 * old_count);
std::copy_n(xx.begin(), old_count, xx.begin() + old_count);

oder

auto old_count = xx.size();
xx.reserve(2 * old_count);
std::copy_n(xx.begin(), old_count, std::back_inserter(xx));

Beim Benutzen reserve, copy_n ist erforderlich, weil die end() iterator zeigt ein Element nach dem Ende … was bedeutet, dass es auch nicht “vor dem Einfügepunkt” des ersten Einfügens liegt und ungültig wird.


23.3.6.5 [vector.modifiers] verspricht das für insert und push_back:

Bemerkungen: Verursacht eine Neuzuweisung, wenn die neue Größe größer als die alte Kapazität ist. Wenn keine Neuzuweisung erfolgt, bleiben alle Iteratoren und Referenzen vor dem Einfügepunkt gültig. Wenn eine Ausnahme ausgelöst wird, außer durch den Kopierkonstruktor, den Verschiebekonstruktor, den Zuweisungsoperator oder den Verschiebezuweisungsoperator von T oder durch eine InputIterator-Operation, gibt es keine Auswirkungen. Wenn eine Ausnahme vom Move-Konstruktor eines Nicht-CopyInsertable-T ausgelöst wird, sind die Auswirkungen nicht angegeben.

  • Die erste Version generiert sowohl auf g++ als auch auf clang ein Memset (plus ein Memmove). Die zweite Version kann zu einem memmove optimiert werden. godbolt.org/z/U2dafw

    – Benutzer202729

    15. März 2020 um 6:16 Uhr


  • Sieht für mich so aus, als ob die erste Version einen zugänglichen Standardkonstruktor für die Größenänderung benötigt, während die zweite nur einen Kopierkonstruktor benötigt.

    – Andreas Lazarus

    24. April 2020 um 2:12 Uhr

  • Für die nächste Frage, wie ich es getan habe: Zusätzlich zu den verschiedenen Iteratoren im ersten Beispiel vector::resize verwendet wird, während in dem Beispiel vector::reserve wird genutzt.

    – Reizo

    30. August 2020 um 22:45 Uhr

Schone Moglichkeit einen Vektor an sich selbst anzuhangen
Borgführer

Ich würde es so machen:

#include <algorithm>
#include <vector>
#include <utility>

int main(int argc, char* argv[])
{
    std::vector<int> v1 = { 1, 2, 3, 4, 5 };

    {
        std::vector<int> v2(v1.begin(), v1.end());
        std::copy(v1.begin(), v1.end(), std::back_inserter(v2));
        std::swap(v1, v2);
    }

    return 0;
}

EDIT: Ich habe eine etwas effizientere Version hinzugefügt.

#include <algorithm>
#include <vector>
#include <utility>

int main(int argc, char* argv[])
{
    std::vector<int> v1 = { 1, 2, 3, 4, 5 };

    {
        typedef std::move_iterator<decltype(v1)::iterator> VecMoveIter;
        std::vector<int> v2(v1);
        std::copy(VecMoveIter(v1.begin()), VecMoveIter(v1.end()), std::back_inserter(v2));
        v1 = std::move(v2);
    }

    return 0;
}

  • Sie haben die Existenz eines Kopierkonstruktors und vergessen std::vector::insert 🙂

    – Chris

    14. Juli 2013 um 5:30 Uhr

  • Kein schlechter Gedanke, da die Vektorinhalte wahrscheinlich sowieso an einen neuen Ort kopiert werden. Aber Sie fügen eine zusätzliche Kopie hinzu. Versuchen Sie, den neuen Vektor mit der richtigen Kapazität im Voraus zu konstruieren.

    – Ben Voigt

    14. Juli 2013 um 5:30 Uhr


  • Außerdem wäre es gut, die vorhandenen Elemente einmal zu kopieren und zu verschieben, anstatt jeweils zwei neue Kopien zu erstellen.

    – Ben Voigt

    14. Juli 2013 um 5:33 Uhr

  • Nun, wenn ich die Zuordnung im Voraus mache, kann ich meine Antwort genauso gut löschen, denn dann wird sie Ihnen. Aber ich stimme dem beweglichen Teil der Dinge zu. Abgesehen davon handelt es sich bei der Frage um einen “schönen Weg” und nicht um “den effizientesten Weg”, und ich finde meine Antwort ziemlich sauber und einfach.

    – Borgführer

    14. Juli 2013 um 6:01 Uhr


  • @Borgleader: Das war nicht der Ort, an dem ich Move verwenden wollte … Ich denke, es gibt einen std::move_iterator Adapter, den Sie mit verwenden können std::copy.

    – Ben Voigt

    14. Juli 2013 um 14:01 Uhr

Zum Anhängen von mehr als einem Slot mit Duplikaten.

    int main() {
        std::vector<int> V;
        V.push_back(1);
        V.push_back(2);

        int oldSize = V.size();
        int newSize = oldSize;
        int nDupSlot = 4;

        V.resize(nDupSlot * oldSize);
        for(int i=0; i<(nDupSlot-1); ++i) {
            std::copy_n(V.begin(), oldSize, V.begin() + newSize);       
            newSize = newSize + oldSize;
         }

        for(int i =0; i<V.size(); ++i) {
            std::cout<<V[i];
            }

        return 0;
    }

Ausgabe:

12121212

Es ist vielleicht nicht der effektivste Weg, aber es ist sicher einfach:

std::vector<int> toAppend(xx);
xx.insert(xx.end(), toAppend.begin(), toAppend.end();

924260cookie-checkSchöne Möglichkeit, einen Vektor an sich selbst anzuhängen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy