Freigeben über


Werttypen (modernes C++)

C++-Klassen sind standardmäßig Werttypen.Dieses Thema bietet eine Übersicht über einführenden Werttypen und Problemen in Bezug auf ihre Verwendung.

Wert VS . Verweistypen

Wie bereits erwähnt C++-Klassen sind standardmäßig Werttypen.Sie können als Verweistypen angegeben werden, die Unterstützung Verhalten ermöglichen, objektorientierte Programmierung zu unterstützen.Werttypen werden manchmal aus der Sicht des Speicher- und Layoutsteuerelements angezeigt, während Referenztypen über Basisklassen und virtuelle Funktionen zu den polymorphen Zwecke sind.Standardmäßig sind Werttypen kopierbar, das bedeutet, dass immer einen Kopierkonstruktor und ein Kopierzuweisungsoperator gibt.Bei Verweistypen legen Sie die Klasse nicht--copyable (deaktivieren Sie den Kopierkonstruktor und den Kopierzuweisungsoperator) und verwenden einen virtuellen Destruktor, der die beabsichtigte Polymorphie unterstützt.Werttypen können auch über den Inhalt, die, wenn sie kopiert werden, Ihnen zwei unabhängige Werte immer geben, die separat geändert werden können.Referenztypen sind über die - Identität ist ein bisschen Objekt es?Aus diesem Grund "Verweistypen" wird auch als "polymorphe Typen".

Wenn Sie einen Verweis ähnlichen Typ (Basisklasse, virtuelle Funktionen) sollen, müssen Sie das Kopieren, wie in der MyRefType-Klasse im folgenden Code gezeigt explizit deaktivieren.

// cl /EHsc /nologo /W4

class MyRefType {
private:
    MyRefType & operator=(const MyRefType &);
    MyRefType(const MyRefType &);
public:
    MyRefType () {}
};

int main()
{
    MyRefType Data1, Data2;
    // ...
    Data1 = Data2;
}

Das Kompilieren des vorangehenden Codes führt den folgenden Fehler:

  
  
  

Werttypen und Verschiebungseffizienz

Kopienzuordnungsmehraufwand wird aufgrund der neuen Kopienoptimierungen vermieden.Wenn Sie beispielsweise eine Zeichenfolge mitten in einem Vektor von Zeichenfolgen einfügen, ist kein Kopienneuzuordnungsmehraufwand, nur eine Drehung, auch wenn sie ein Wachsung Vektor selbst ergibt.Dies gilt auch für andere Vorgänge auf und beispielsweise führt einen Hinzufügensvorgang auf zwei sehr großen Objekten aus.Wie können Sie diese Wertsvorgangsoptimierungen?In einigen C++-Compilern ermöglicht der Compiler dieses für Sie implizit, ähnlich wie Kopierkonstruktoren kann durch den Compiler automatisch generiert werden.In Visual C++, muss die Klasse "abonnieren", um Zuweisung und Konstruktoren zu verschieben, indem sie sie in der Klassendefinition deklariert.Dies wird erreicht, indem doppelte rvalu-Verweis des kaufmännischen Und-Zeichens (&&) in den entsprechenden Memberfunktionsdeklarationen verwendet und Verschiebungskonstruktor- und Verschiebungszuweisungsmethoden definiert.Sie müssen auch den richtigen Code einfügen "stehlen die Eingeweide" aus dem Quellobjekt heraus.

Wie entscheiden Sie, wenn Sie die aktivierte Verschiebung erfordern?Wenn Sie bereits wissen, benötigen Sie die Kopienkonstruktion, die aktiviert ist, möchten Sie wahrscheinlich, die Verschiebung, die aktiviert ist, wenn sie als eine Tiefenkopie billiger sein kann.Wenn Sie jedoch wissen, benötigen Sie Verschiebungsunterstützung, bedeutet dies nicht unbedingt, dass Sie die aktivierte Kopie soll.Dieser letzte Fall würde einen "nur für Verschiebung Typ" aufgerufen.Ein Beispiel bereits in der Standardbibliothek ist unique_ptr.Als Randbemerkung wird alte auto_ptr veraltet und wurde durch unique_ptr genau aufgrund des Mangels an Verschiebesemantikunterstützung in der früheren Version von C++ ersetzt.

Mit Verschiebesemantik verwenden, können Sie EINGABETASTE-durchWert oder EINFG-in-mittleres.Verschiebung ist eine Optimierung der Kopie.Es gibt Anforderung für Heapreservierung als Problemumgehung.Betrachten Sie folgenden Pseudocode:

#include <set>
#include <vector>
#include <string>
using namespace std;

//...
set<widget> LoadHugeData() {
    set<widget> ret;
    // ... load data from disk and populate ret
    return ret;
}
//...
widgets = LoadHugeData();   // efficient, no deep copy

vector<string> v = IfIHadAMillionStrings();
v.insert( begin(v)+v.size()/2, "scott" );   // efficient, no deep copy-shuffle
v.insert( begin(v)+v.size()/2, "Andrei" );  // (just 1M ptr/len assignments)
//...
HugeMatrix operator+(const HugeMatrix& , const HugeMatrix& );
HugeMatrix operator+(const HugeMatrix& ,       HugeMatrix&&);
HugeMatrix operator+(      HugeMatrix&&, const HugeMatrix& );
HugeMatrix operator+(      HugeMatrix&&,       HugeMatrix&&);
//...
hm5 = hm1+hm2+hm3+hm4+hm5;   // efficient, no extra copies

Hh438479.collapse_all(de-de,VS.110).gifAktivieren der Verschiebung für entsprechende Werttypen

Eine Wert ähnliche Klasse, in der Verschiebung als eine Tiefenkopie billiger sein kann, Verschiebungskonstruktion und Verschiebungszuweisung Effizienzgründen aktivieren.Betrachten Sie folgenden Pseudocode:

#include <memory>
#include <stdexcept>
using namespace std;
// ...
class my_class {
    unique_ptr<BigHugeData> data;
public:
    my_class( my_class&& other )   // move construction
        : data( move( other.data ) ) { }
    my_class& operator=( my_class&& other )   // move assignment
    { data = move( other.data ); return *this; }
    // ...
    void method() {   // check (if appropriate)
        if( !data ) 
            throw std::runtime_error("RUNTIME ERROR: Insufficient resources!");
    }
};

Wenn Sie Kopienkonstruktion/-Zuweisung aktivieren, aktivieren Sie auch Verschiebungskonstruktion/-Zuweisung, wenn sie als eine Tiefenkopie billiger sein kann.

Eine Nicht Werts typen sind, wie nur für Verschiebung, wenn Sie eine Ressource nicht klonen können, nur Übergangsbesitz.Beispiel: unique_ptr

Abschnitt

Inhalt

Siehe auch

Konzepte

C++-Typsystem modernes (C++)

Weitere Ressourcen

Willkommen zurück in C++ modernes (C++)

C++-Sprachreferenz

C++-Standardbibliothek-Referenz