Comment fonctionne la bibliothèque standard de mettre en œuvre des std::swap?
Quelle est la fonction d'échange de la mise en œuvre de la STL? Est-il aussi simple que cela:
template<typename T> void swap(T& t1, T& t2) {
T tmp(t1);
t1=t2;
t2=tmp;
}
Dans d'autres postes, ils parlent spécialisé cette fonction pour votre propre classe. Pourquoi aurais-je besoin de faire cela? Pourquoi ne puis-je pas utiliser le std::swap
fonction?
- C'est exactement comment
std::swap
a été implémenté en C++03, en C++11, il estT tmp(std::move(t1)); t1 = std::move(t2); t2 = std::move(tmp);
que ce sera plus efficace que de copier pour certains types. - Il n'existe pas de "la bibliothèque standard". Il y a un tas d'implémentations, choisissez-en un ou quelques-uns et le regarder.
- Chacune de ces implémentations met en œuvre "Le C++ standard Library" (voir §17.1/1
- Il est, cependant, pas "le TSL". La Bibliothèque Standard n'est pas la STL.
- Il est totalement "le TSL". C'est une bibliothèque C++ écrit par SGI, qui a ressemblance frappante avec la norme C++ de la bibliothèque. sgi.com/tech/stl/table_of_contents.html
Vous devez vous connecter pour publier un commentaire.
Comment est
std::swap
mis en œuvre?Oui, la mise en œuvre présentées dans la question, la classique C++03 un.
Plus moderne du C++(C ++ 11) la mise en œuvre de
std::swap
ressemble à ceci:C'est une amélioration par rapport à la classique C++03 mise en œuvre en termes de gestion des ressources, car il empêche les copies inutiles, etc. C', le C++11
std::swap
, requiert le typeT
être MoveConstructible et MoveAssignable, permettant ainsi la mise en œuvre et les améliorations.Pourquoi aurais-je besoin de fournir une implémentation personnalisée?
Une implémentation personnalisée de
swap
, pour un type spécifique, est généralement conseillé lors de la mise en œuvre est plus efficace ou plus spécifique que la version standard.Un exemple classique de cela est lorsque votre classe gère une grande quantité de ressources qui pourraient être coûteuses à copier, puis supprimer. Au lieu de cela, votre custom mise en œuvre pourrait tout simplement échanger les poignées ou des pointeurs est nécessaire pour effectuer l'échange.
Avec l'avènement de
std::move
et de meubles des types (et de la mise en œuvre de votre type en tant que tel), circa C++11 et au-delà, beaucoup de l'original de raisonnement commence à tomber; mais néanmoins, si une coutume swap serait mieux que le standard, la mettre en œuvre.Générique code sera généralement en mesure d'utiliser votre personnalisé
swap
si il utilise le ADL mécanisme de manière appropriée.swap
est conçu pour faire exactement cela, a minimisé les exigences sur vous pour prolonger ou de personnaliser la mise en œuvre standard (ce qui est une bonne chose à mon avis).swap
mise en œuvre, alors vous pourriez écrire un plus efficace de swap de trois coups par ne pas s'embêter avec que le programme d'installation. Cela fait beaucoup de "si" bien sûr, mais supposons qu'un déplacé-de l'objet est défini comme "le vide" et un objet "vide" contient tout un tas de zéros et peut-être un mannequin nœud de la structure. C'est un peu écrit, trois fois. Donc, normalement négligeable, mais vous pourriez le faire pour l'exécution si elle se pose.swap
fonction membre peut temporairement en rupture invariants si cela est plus rapide que de faire trois mouvements qui ont à maintenir les invariants après chaque mouvement. Si il y a une efficaceX::swap(X&)
membre puis se spécialiseswap(X&, X&)
appeler cela a du sens. Certaines opérations de déplacement pourrait même être mis en œuvre en termes deswap
membre, de sorte que le génériquestd::swap
fonction serait d'appeler leswap
membre trois fois, quand il ne doit être effectuée qu'une fois.Dont la mise en œuvre? C'est un cahier des charges, pas un seul de béton de la bibliothèque. Si vous voulez dire comment mon compilateur standard de la bibliothèque de il, soit nous dire quel compilateur, ou de lire le code vous-même.
C'est essentiellement la version naïve de pré-C++11.
Cet spécialisée des nations unies mise en œuvre des forces d'une copie: pour
T = std::vector<SomethingExpensive>
dans votre exemple, le code se traduit comme:donc à l'échange de deux vecteurs nous avons essentiellement créé trois. Il y avait trois allocations dynamiques et beaucoup de chers objets copiés, et l'un quelconque de ces opérations pourrait jeter, en laissant éventuellement les arguments dans un état indéterminé.
Depuis toute évidence, c'était horrible, les surcharges ont été fournis pour cher conteneurs, et vous avez été invités à écrire des surcharges pour votre propre cher types: par exemple. le
std::vector
spécialisation eu accès au vecteur-même, et pourrait permuter deux vecteurs sans la copie:Note que cela implique d'aucune copie de quoi que ce soit cher, pas de dynamique (de)l'allocation, et il est garanti de ne pas jeter.
Maintenant, la raison de cette spécialisation est que le vecteur::swap a accès à du vecteur internes, et peuvent en toute sécurité et efficacement les déplacer sans les copier.
Pré-C++11, pour la même raison que
std::vector
- pour faire la permutation efficace et d'exception-safe.Depuis C++11, vous n'avez pas vraiment - si vous devez fournir déplacer de la construction et de l'affectation ou le compilateur peut générer des valeurs par défaut saines pour vous.
Le nouveau générique de swap:
pouvez utiliser move de la construction/la cession d'obtenir essentiellement le même comportement que la coutume vecteur de mise en œuvre ci-dessus, sans avoir à écrire une implémentation personnalisée à tous.
swap
et choisissez "Aller À la Définition".