Les valeurs R semblent fournir un support incomplet pour les temporaires non nommés, ou est-ce que quelque chose me manque?Les valeurs R semblent fournir un support incomplet pour les temporaires sans nom, ou est-ce que quelque chose me manque?
11 C++ fournit un excellent support pour rvalues à mettre en œuvre la sémantique de déplacement, utiles pour convertir coûteux et copier des cycles affecter en mouvements rapides et bon marché à temps constant, semblables à moving une référence. Mais C++ 11 est arrivé tard dans le jeu, et à ce moment-là, j'avais une solution complète au problème temporaire coûteux, sans nom, en utilisant la solution basée sur les classes décrite ci-dessous. Ce n'est que lorsque j'ai récemment tenté de remplacer ma solution par des constructeurs de mouvement C++ 11 «modernes», que j'ai découvert que la gestion de rvalue ne couvre pas les cas importants couverts par la solution basée sur les classes. Un exemple représentatif est l'expression A + B. Lorsque A est un temporaire non nommé (rvalue), une implémentation sur place de A + = B est appropriée, quand A n'est pas un temporaire sans nom (lvalue), A + B calcule un nouveau résultat. Mais le support de C + 11 rvalue semble n'adresser qu'un bon argument, mais pas un rvalue de gauche.
Par extension, cette limitation affecte tous les autres opérateurs et fonctions du type de base qui pourraient bénéficier de traiter * ceci comme valeur de référence le cas échéant. Notez que A + B peut même être calculé comme B + = A, quand A est une lvalue et B est une rvalue. Les avantages d'une solution complète peuvent souvent être appliqués plus à ces valeurs qu'aux bons arguments. Si C++ 11 ne fournit qu'une demi-solution ici, la solution basée sur les classes ci-dessous reste significativement supérieure pour beaucoup de choses. Est-ce que j'ai râté quelque chose?
Donc, nous allons déduire une classe T temporaire sans nom de la classe des valeurs S, ajouter des constructeurs appropriés, les affectations, les opérateurs et les fonctions de S et T, puis remplacer T S comme type de retour pour toutes les fonctions et les opérateurs qui retourne un résultat S. Avec cela, nous obtenons tous la même sémantique de mouvement qu'avec des valeurs, ainsi que la prise en charge de fonctions et d'opérateurs supplémentaires qui peuvent fonctionner plus rapidement sur des valeurs temporaires non nommées sur place.
class S { // S is a sample base type to extend
protected:
mutable char* p; // mutable pointer to storage
mutable int length; // mutable current length
mutable int size; // mutable current size
public:
~S (); // S destructor
S (char* s); // construct from data
S (const S& s); // from another S
S (const T& s); // construct from an unnamed temporary
T& result () { return (T&)*this; } // cast *this into a T& (an equivalent to std::move (*this))
S& take (S& s); // free *this, move s to *this, put s in empty/valid state
S& operator= (const S& s); // copy s to *this
S& operator= (const T& s); // assign from unnamed temporary using take ()
S& operator+= (const S& v); // add v to *this in-place
S& operator-= (const S& v); // subtract v from *this in-place
S& operator<<= (Integer shift); // shift *this in-place
S& operator>>= (Integer shift);
T operator+ (const S& v); // add v to *this and return a T
T operator- (const S& v); // subtract v from *this and return a T
etc...
};
class T : public S { // T is an unnamed temporary S
private:
T& operator= (const T& s); // no public assignments
void* operator new (size_t size); // don't define -- no heap allocation
void operator delete (void* ptr);
public:
T (char* s) : S (s) { }; // create a new temporary from data
T (const S& s) : S (s) { }; // copy a new temporary from a non-temporary
T (const T& s) : S (s) { }; // move a temporary to new temporary
T operator<< (int shift) const { return ((S&)*this <<= shift).result (); }
T operator>> (int shift) const { return ((S&)*this >>= shift).result (); }
T operator+ (const S& v) const { return ((S&)*this += v).result (); }
T operator- (const S& v) const { return ((S&)*this -= v).result (); }
};
Notez que cette méthode a démontré sa justesse et de l'efficacité à travers une variété de types de données complets (y compris les chaînes, les tableaux, les grands entiers, etc.) depuis 2001, il fonctionne sans aucune référence à 11 C++ caractéristiques et ne repose sur aucune fonctionnalité de langage indéfini.
Vous recherchez * ref-qualifier * s. –
Cette question est très verbeuse et pas particulièrement claire. Pourriez-vous le retravailler pour poser une question simple au sujet de C++ s'il vous plaît. Imaginez que nous n'avons jamais vu votre classe auparavant et que vous ne savez pas pourquoi c'est nécessaire. (indice: ce n'est probablement pas le cas) –
Comment utilisez-vous 'T'? Avez-vous besoin de garder une trace de la variable temporaire et d'effectuer des copies pour convertir les non-temporaires en temporaires? – nwp