Warum std :: make_move_iterator an Vektorzeichenfolge, aber nicht an Vektorzeichen arbeitet

8

Ich habe erwartet, dass std::make_move_iterator immer Inhalte verschieben wird, aber es scheint nicht.

Es sieht so aus, als ob Elemente in vector<string> verschoben werden, aber nicht in vector<int> .

Siehe das folgende Code-Snippet:

%Vor%

Das Ergebnis ist:

%Vor%

Ich bin bei Ubuntu 14.04, gcc 4.8.2 und der Code ist mit -std=c++11

kompiliert

Können Sie erklären, warum std::make_move_iterator ein anderes Verhalten in vector<int> und vector<string> hat? (Oder ist es ein Fehler?)

    
Mine 29.07.2014, 06:27
quelle

2 Antworten

14

Das Verhalten wird erwartet. Eine Bewegung von beiden Vektoren belässt die ursprüngliche v1 mit 5 verschobenen Elementen in ihrer zweiten Hälfte.

Der Unterschied besteht darin, dass beim Verschieben der Strings leere Strings zurückbleiben. Dies liegt daran, dass es eine sehr effiziente Möglichkeit ist, Zeichenketten zu verschieben und die verschobene Zeichenkette in einem selbstkonsistenten Zustand zu belassen (Technisch könnten sie den Wert "Hello, World, nice move!" behalten, aber das würde zusätzliche Kosten verursachen). Die Quintessenz ist, dass Sie die von Strings verschobenen Zeichen nicht in Ihrer Ausgabe sehen.

Im Fall der Vektoren int gibt es keine Möglichkeit, eine int zu verschieben, die effizienter ist als das Kopieren, also werden sie einfach überkopiert.

Wenn Sie die Größe der Vektoren überprüfen, sehen Sie, dass die v1 in beiden Fällen die Größe 10 haben.

Hier ist ein vereinfachtes Beispiel um zu verdeutlichen, dass die aus Strings verschobenen Zeichen leer bleiben:

%Vor%

Ausgabe:

%Vor%     
juanchopanza 29.07.2014, 06:35
quelle
3

Wenn wir von move sprechen, sprechen wir nicht davon, das Objekt selbst zu bewegen (es bleibt intakt). Was bewegt wird, sind seine internen Daten. Dies kann den Wert des Objekts, dessen interne Daten verschoben werden, beeinflussen oder nicht.

Aus diesem Grund verliert Ihr int -Array nicht seine ursprüngliche int s. Was Ihr Beispiel betrifft, hat es immer noch das ursprüngliche std::strings , genau wie das int Beispiel, aber die internen Werte haben sich in leere Strings geändert.

Es ist wichtig, daran zu denken, dass intern ein std::string (im Wesentlichen) einen Zeiger auf ein Zeichen-Array enthält. Wenn Sie kopieren ein std::string kopieren Sie jedes Element des Zeichenarrays. Ein move vermeidet jedoch das Kopieren, indem stattdessen der interne Zeiger kopiert wird.

Aber wenn die Operation move dort angehalten würde, würde sowohl std::string s auf das gleiche Zeichenarray zeigen als auch die Zeichendaten ändern, auf die entweder std::string zeigt, würde auch die anderen verändern. Wenn Sie also eine Zeichenfolge verschieben, reicht es nicht aus, nur den internen Zeiger zu kopieren , sondern Sie müssen den internen Zeiger des std::string vom Punkt auf einen neuen setzen leeres Zeichen-Array, so dass es die Zeichenfolge nicht mehr beeinflussen kann, in die die Daten verschoben wurden.

Beim Verschieben von int ist nach dem Kopieren der Daten keine weitere Aktion erforderlich. Es gibt keine Zeiger, so dass nach der Kopie beide Ints unabhängige Daten enthalten.

    
Galik 29.07.2014 07:37
quelle