Double Possible:
La sémantique de déplacement == custom fonction d'échange obsolète?C'est combien de
std::swap
ressemble au C++11:template<typename T> void swap(T& x, T& y) { T z = std::move(x); x = std::move(y); y = std::move(z); }
Dois-je continuer à se spécialiser
std::swap
pour mes propres types, ou seront -std::swap
être aussi efficace qu'elle obtient, à condition que les élèves de ma classe définit un constructeur de déplacement et un opérateur d'assignation de déplacement, de cours?
Réponses
Trop de publicités?La spécialisation de l' std::swap
est désormais facultative, mais pas obsolète. La justification est la performance.
Pour le prototypage de code, et peut-être même pour beaucoup de code de la navigation, std::swap
sera beaucoup rapide. Toutefois, si vous êtes dans une situation où vous avez besoin de eek tous peu à partir de votre code, l'écriture d'un personnalisé swap peut-être encore un avantage de performance significative.
Considérons le cas où votre classe est essentiellement un propriétaire de pointeur et de votre constructeur de déplacement et d'assignation de déplacement juste avoir à traiter avec un pointeur. Le comte de la machine charges et les stocke pour chaque membre:
Constructeur de déplacement: 1 chargez et 2 magasins.
Assignation de déplacement: 2 charges et 2 magasins.
Personnalisé swap: 2 charges et 2 magasins.
std::swap
est de 1 déplacez la construction et de 2 déplacez les affectations ou les: 5 charges et 6 magasins.
Une coutume swap est potentiellement encore deux ou trois fois plus rapide que l' std::swap
. Si toute fois vous êtes à essayer de comprendre la vitesse de quelque chose en comptant les charges et les magasins, les deux vont être méchant rapide.
Remarque: Dans le calcul du coût de votre déménagement affectation, assurez-vous de prendre en compte que vous allez être en mouvement dans un déplacé-de valeur (en std::swap
de l'algorithme). Souvent, cela annule le coût d'une libération, mais au prix d'une branche.
Est spécialisée std::swap obsolète maintenant que nous avons la sémantique de déplacement?
Pas de. C'est la version générique, mais vous pouvez l'optimiser pour passer d'un troisième opération de déplacement. Ma préférence est de combiner copie&swap idiome de la personnalisation de std::swap pour mes cours.
Cela signifie que je vais avoir:
class Aaaa { public: Aaaa(); // not interesting; defined elsewhere Aaaa(Aaaa&& rvalueRef); // same Aaaa(const Aaaa& ref); // same ~Aaaa(); // same Aaaa& operator=(Aaaa object) // copy&swap { swap(object); return *this; } void swap(Aaaa& other) { std::swap(dataMember1, other.dataMember1); std::swap(dataMember2, other.dataMember2); // ... } // ... }; namespace std { template<> inline void std::swap(Aaaa& left, Aaaa& right) { left.swap(right); } }
Cela dépendra de votre Type.
Vous pourrez le déplacer de x à z, à partir de y à x, de z à y. C'est trois opérations de copie de la représentation sous-jacente (peut-être seulement un pointeur, peut-être quelque chose de plus, qui sait)
Maintenant peut-être vous pouvez créer une plus rapide swap pour votre type (xor swap trick, assembleur en ligne, ou peut-être std::swap pour votre sous-jacente types est juste plus rapide).
Ou peut-être aussi votre compilateur est bon à optimiser, et essentiellement optimise les deux cas, dans les mêmes instructions (comme ont temporaire dans un registre).
Personnellement, j'ai tendance à toujours mettre en œuvre un swap de membre de la fonction qui va être appelée à partir de plusieurs endroits, y compris des choses comme le mouvement d'affectation, mais YMMV.
Cette swap()
appelle un constructeur de déplacement et de 2 déplacez les affectations. Je pense que l'on peut écrire plus efficace, swap()
de son type particulier de classe,
class X
{
int * ptr_to_huge_array;
public:
// ctors, assgn ops. etc. etc.
friend void swap(X& a, X& b)
{
using std::swap;
swap(a.ptr_to_huge_array, b.ptr_to_huge_array);
}
};
indépendamment de la mise en œuvre de déplacer le constructeur et l'opérateur d'affectation.