2013-07-14 19 views
15

Ich möchte hängen Sie den Inhalt des Vektors duplizieren und will, dass sie am Ende des ursprünglichen Vektors dh v[i]=v[i+n] for i=0,2,...,n-1Nizza Art und Weise einen Vektor selbst

ich für eine nette Art und Weise bin auf der Suche angehängt werden, es zu tun, nicht mit einer Schleife. Ich sah std::vector::insert, aber die iterative Version verbietet einen Iterator zu *this (d. H. Verhalten ist nicht definiert).

Ich habe auch versucht std::copy wie folgt (aber in Segmentierungsfehler in Folge):

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

+0

möglich Duplikat [Falsche Ergebnisse, wenn Vektor selbst anhängt Kopie mit und zurück \ _inserter] (http://stackoverflow.com/questions/11511510/wrong-results-when-appending-vector-to-itself-using-copy-and-back-inserter) –

+1

@BenVoigt, Um fair zu sein, Als ich diese Frage gestellt habe, habe ich es versucht und wollte zu wissen, warum es nicht funktioniert hat. Ich brauchte eigentlich keine elegante Arbeitslösung, daher gibt es nur Erwähnungen in den Kommentaren. – chris

+1

Ich frage mich, ob die meisten Menschen die Implementierung zum ersten Mal richtig gemacht hätten, wenn sie es mit einer Schleife codiert hätten. – MarkB

Antwort

21

Wow. So viele Antworten, die nah sind, keine mit den richtigen Stücken. Sie benötigen beide resize (oder reserve) und copy_n, zusammen mit der ursprünglichen Größe zu erinnern.

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

reserve Wenn verwendet, wird copy_n erforderlich, da die end() Iterator zeigt ein Element über das Ende ..., die es bedeutet auch nicht „vor dem Einfügungspunkt“ der ersten Einfügen und wird ungültig.


23.3.6.5 [vector.modifiers] Versprechen, dass für insert und push_back:

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

3

Ich würde es tun, wie folgt:

#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; 
} 
+0

Sie haben die Existenz eines Kopierkonstruktors und 'std :: vector :: insert' vergessen :) – chris

+0

Kein schlechter Gedanke, denn der Vektorinhalt wird wahrscheinlich sowieso an einen neuen Ort kopiert. Aber Sie fügen eine zusätzliche Kopie hinzu. Versuchen Sie, den neuen Vektor mit der richtigen Kapazität im Vordergrund zu konstruieren. –

+0

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

0

Zum Anhängen von mehr als einem Steckplatz von 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; 
    } 

Ausgang:

12121212 
0

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

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