Partager via


Types valeur (C++ moderne)

Les classes C++ sont par défaut des types valeur.Cette rubrique fournit une vue d'ensemble préliminaire les types valeur et les problèmes concernant leur utilisation.

Valeur VS. des types référence

Comme indiqué précédemment, les classes C++ sont par défaut des types valeur.Elles peuvent être spécifiées comme types référence, qui permettent au comportement polymorphe de prendre en charge la programmation orientée objet.Les types valeur sont parfois affichés du point de vue du contrôle de mémoire et de disposition, alors que les types référence sont sur les classes de base et les fonctions virtuelles à des fins polymorphes.Par défaut, les types valeur sont copyable, ce qui signifie qu'il existe toujours un constructeur de copie ou un opérateur d'assignation de copie.Pour les types référence, vous rendez la classe non-copyable (désactivez le constructeur de copie et l'opérateur d'assignation de copie) et utilisez un destructeur virtuel, qui prend en charge le polymorphisme prévu.Les types valeur sont également sur le contenu, qui, lorsqu'ils sont copiés, vous donne toujours deux valeurs individuelles qui peuvent être modifiées séparément.Les types référence sont sur l'identité – genre l'objet est -t-elle ?Pour cette raison, « types référence » sont également sous le nom « des types polymorphes ».

Si vous souhaitez réellement un type comme une référence (classe de base, fonctions virtuelles), vous devez désactiver explicitement la copie, comme indiqué dans la classe d' MyRefType dans le code suivant.

// cl /EHsc /nologo /W4

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

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

Compiler le code ci-dessus entraîne l'erreur suivante :

  
  
  

Types valeur et efficacité de mouvements

La surcharge d'allocation de copie est évitée en raison de nouvelles optimisations de copie.Par exemple, lorsque vous insérez une chaîne au milieu d'un vecteur des chaînes, il n'y a pas de charge de redistribution de copie, seul un déplacement même s'il provoque un développement du vecteur lui-même.Cela s'applique également à d'autres opérations, par exemple l'exécution d'une opération d'ajout de deux objets volumineux.Comment activez-vous ces optimisations d'exécution de valeur ?Dans certains compilateurs C++, le compilateur activera opération pour vous implicitement, comme les constructeurs de copie peut être généré automatiquement par le compilateur.Toutefois, dans Visual C++, votre classe aura besoin de « opération » pour déplacer l'assignation et les constructeurs en le déclarant dans la définition de classe.Cela est accompli en utilisant la double référence rvalue de perluète (&&) dans les déclarations et définir de fonction membre approprié des méthodes de constructeur de mouvements et d'assignation de déplacement.Vous devez également insérer du code correct « volez les entrailles » hors de l'objet source.

Comment décidez-vous si vous avez besoin de mouvements activé ?Si vous connaissez déjà vous avez besoin de la construction de copie activée, vous souhaiterez probablement le déplacement activé s'il peut être moins cher qu'une copie complète.Toutefois, si vous savez vous avez besoin de la prise en charge de déplacement, il ne signifie pas nécessairement que vous souhaitez copier activée.Ce dernier cas est appelé « un type réservé au déplacement ».Un exemple déjà dans la bibliothèque standard est unique_ptr.Comme note marginal, auto_ptr ancien est déconseillé, et a été remplacé par unique_ptr précisément en raison de l'échec de prise en charge de la sémantique de déplacement dans la version antérieure de C++.

À l'aide de la sémantique de déplacement vous pouvez retour-par- valeur ou INSERT-dans- méthode.Le déplacement est une optimisation de copie.Il y a besoin d'allocation du tas en tant que solution de contournement.Prenons le pseudo-code suivant :

#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(fr-fr,VS.110).gifActivation du déplacement pour les types valeur appropriés

Pour une classe comme une valeur où le déplacement peut être moins cher qu'une copie complète, activer la construction de déplacement et l'assignation de mouvements pour l'efficacité.Prenons le pseudo-code suivant :

#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!");
    }
};

Si vous activez la construction/assignation de copie, activez également la construction/assignation de mouvements s'il peut être moins cher qu'une copie complète.

Certains types non valeur sont réservés au déplacement, par exemple lorsque vous ne pouvez pas cloner une ressource, seule propriété de migration.Par exemple : unique_ptr

Section

Contenu

Voir aussi

Concepts

Système de type C++ (C++ moderne)

Autres ressources

Accueil vers C++ (C++ moderne)

Guide de référence du langage C++

Référence de la bibliothèque C++ standard