Move-Konstruktoren und Statische Arrays
Ich habe die Möglichkeiten der Bewegen Konstruktoren in C++, und ich Frage mich, was sind einige Möglichkeiten der Einnahme von Vorteil, diese Funktion an einem Beispiel, wie unten. Betrachten Sie diesen code:
template<unsigned int N>
class Foo {
public:
Foo() {
for (int i = 0; i < N; ++i) _nums[i] = 0;
}
Foo(const Foo<N>& other) {
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other) {
//??? How can we take advantage of move constructors here?
}
//... other methods and members
virtual ~Foo() { /* no action required */ }
private:
int _nums[N];
};
Foo<5> bar() {
Foo<5> result;
//Do stuff with 'result'
return result;
}
int main() {
Foo<5> foo(bar());
//...
return 0;
}
In diesem obigen Beispiel, wenn wir verfolgen das Programm (mit MSVC++ 2011), sehen wir, dass Foo<N>::Foo(Foo<N>&&)
aufgerufen wird, wenn der Bau foo
, die das gewünschte Verhalten. Allerdings, wenn wir nicht Foo<N>::Foo(Foo<N>&&)
, Foo<N>::Foo(const Foo<N>&)
aufgerufen werden würde, statt, das würde eine redundante Kopie Betrieb.
Meine Frage ist nun, wie bereits im code, die mit diesem spezifischen Beispiel welches mit einem statisch zugewiesenen einfaches array, gibt es eine Möglichkeit zu nutzen die move-Konstruktor, um dies zu vermeiden, wird die redundante Kopie?
Du musst angemeldet sein, um einen Kommentar abzugeben.
First off, es ist eine Allgemeine Art von Beratung, die sagt, man sollte nicht schreiben, copy/move-Konstruktor, Zuweisungsoperator oder Destruktor an, wenn Sie ihm helfen kann, und eher verfassen deine Klasse von hochwertigen Komponenten, die wiederum diese, so dass die Standard-Funktionen generiert, Das Richtige zu Tun. (Die umgekehrte Implikation ist, dass, wenn Sie haben, schreiben Sie einer von denen, die Sie haben wahrscheinlich schreiben alle von Ihnen).
Also die Frage läuft darauf hinaus, "die einzigen Verantwortung Komponente Klasse können die Vorteile der move-Semantik?" Die Allgemeine Antwort ist: Alles, was die Verwaltung einer Ressource. Der Punkt ist, dass der move-Konstruktor/zuordner wird nur setzen Sie die Ressource, die zu der neuen Sache und Verfall der alten, so dass die (vermutete teuer oder unmöglich) neue Aufteilung und Tiefe kopieren der Ressource.
Das Paradebeispiel ist alles, was dynamischen Speicher verwaltet, wo Sie den Verschiebevorgang einfach Kopien der Zeiger und setzt die alte Objekt den Zeiger auf null (also die alten Objekts Destruktor nichts macht). Hier ist ein naives Beispiel:
Der Schlüssel ist, dass jede Kopie/move-Konstruktor wird eine vollständige kopieren der member-Variablen; es ist nur, wenn diese Variablen sind in sich selbst behandelt oder Verweise auf Ressourcen, die Sie vermeiden können, kopieren Sie die Ressource, wegen der Vereinbarung, die einem bewegten Objekt ist nicht mehr gültig und du bist frei, um es stehlen. Wenn es nichts zu stehlen, dann gibt es keinen Vorteil in der Bewegung.
In diesem Fall ist es nicht nützlich ist, weil
int
hat keine move-Konstruktoren.Jedoch, es könnte nützlich sein, wenn diejenigen, die waren Zeichenketten statt, zum Beispiel:
Nun vermeiden Sie das kopieren von strings, wo eine Bewegung zu tun. Ich bin mir nicht sicher, ob ein konformer C++11 compiler generiert entsprechenden code, wenn du weglassen, alle die kopieren-/verschieben-Konstruktoren komplett, sorry.
(In anderen Worten, ich bin nicht sicher, ob
std::move
ist speziell definiert, um ein element-Weise für arrays.)Für die Klasse Vorlage, die Sie schrieb, es gibt keinen Vorteil zu nehmen, in der ein move-Konstruktor.
Wäre es von Vorteil, wenn das Mitglied-array wurde dynamisch zugewiesen. Aber mit einem einfachen array als member, es gibt nichts zu optimieren, können Sie nur kopieren die Werte. Es gibt keinen Weg, um bewegen Sie.
In der Regel, bewegen-semantische implementiert, wenn die Klasse verwaltet Ressource. Da in Ihrem Fall die Klasse nicht verwaltet Ressource, die move-semantic wäre mehr wie copy-semantische, da gibt es nichts zu verschoben.
Besser zu verstehen, wenn move-semantic notwendig wird, sollten Sie
_nums
einen pointer statt einem array: