Question

A quoi sert std::pair, pourquoi devrais-je l'utiliser et quels avantages boost::compressed_pair apporte-t-il?

Était-ce utile?

La solution

std::pair est un type de données permettant de regrouper deux valeurs en tant que un seul objet. std::map l'utilise pour les paires clé / valeur.

Pendant que vous apprenez pair , vous pouvez consulter tuple . C'est comme <=> mais pour grouper un nombre arbitraire de valeurs. <=> fait partie de TR1 et de nombreux compilateurs l’incluent déjà dans leurs implémentations de bibliothèque standard.

Consultez également le chapitre 1, & "Tuples, &"; du livre Les extensions de la bibliothèque standard C ++: didacticiel et référence de Pete Becker, ISBN-13: 9780321412997, pour une explication détaillée.

alt text

Autres conseils

compressed_pair utilise une astuce de modèle pour économiser de l'espace. En C ++, un objet (petit o) ne peut pas avoir la même adresse qu'un objet différent.

Donc, même si vous avez

struct A { };
La taille de

A ne sera pas 0, car alors:

A a1;
A a2;
&a1 == &a2;

tiendra, ce qui n'est pas autorisé.

Mais de nombreux compilateurs feront ce qu'on appelle & l'optimisation de la classe de base vide & ";:

.
struct A { };
struct B { int x; };
struct C : public A { int x; };

Ici, il est normal que B et C aient la même taille, même si sizeof(A) ne peut pas être zéro.

Donc boost::compressed_pair tire parti de cette optimisation et héritera, si possible, de l'un ou l'autre des types de la paire s'il est vide.

Donc, un std::pair pourrait ressembler à (j'ai déjà fait une bonne affaire, ctors, etc.):

template<typename FirstType, typename SecondType>
struct pair {
   FirstType first;
   SecondType second;
};

Cela signifie que si FirstType ou SecondType est pair<A, int>, votre sizeof(int) doit être supérieur à compressed_pair<A,int>.

Mais si vous utilisez <=>, son code généré ressemblera à:

 struct compressed_pair<A,int> : private A {
    int second_;
    A first() { return *this; }
    int second() { return second_; }
 };

Et <=> ne sera aussi gros que sizeof (int).

Vous devez parfois renvoyer 2 valeurs d'une fonction et il est souvent excessif de créer une classe rien que pour cela.

std: pair est utile dans ces cas.

Je pense que boost: comprim_pair est capable d’optimiser les membres de taille 0. Ce qui est surtout utile pour les machines à gabarit lourd dans les bibliothèques.

Si vous contrôlez les types directement, cela n'a aucune importance.

Cela peut paraître étrange d’entendre que comprim_pair se soucie de quelques octets. Mais cela peut en réalité être important lorsque l’on détermine où compress_pair peut être utilisé. Par exemple, considérons ce code:

boost::function<void(int)> f(boost::bind(&f, _1));

Cela peut soudainement avoir un impact important d’utiliser comprim_pair dans les cas ci-dessus. Que pourrait-il se passer si boost :: bind stocke le pointeur de fonction et le titulaire _1 en tant que membres en soi ou dans un std::pair en soi? Eh bien, cela pourrait gonfler jusqu’à sizeof(&f) + sizeof(_1). En supposant qu'un pointeur de fonction a 8 octets (ce qui n'est pas inhabituel, en particulier pour les fonctions membres) et que l'espace réservé a un octet (voir la réponse de Logan pour savoir pourquoi), nous aurions pu avoir besoin de 9 octets pour l'objet bind. En raison de l'alignement, cela pourrait gonfler jusqu'à 12 octets sur un système 32 bits habituel.

boost::function encourage ses implémentations à appliquer une optimisation de petit objet. Cela signifie que pour les petits foncteurs, un petit tampon directement intégré à l'objet compressed_pair est utilisé pour stocker le foncteur. Pour les plus grands foncteurs, le tas devrait être utilisé en utilisant l'opérateur new pour obtenir de la mémoire. À propos de la version 1.34 , il a été décidé d'adopter cette optimisation , car il était prévu de gagner de très grands avantages en termes de performances.

Maintenant, une limite raisonnable (mais peut-être encore assez petite) pour un tampon aussi petit serait de 8 octets. En d’autres termes, notre objet de liaison, assez simple, ne pourrait pas rentrer dans la petite mémoire tampon, et exigerait que l’opérateur new soit stocké. Si l'objet de liaison ci-dessus utilise un <=>, il peut réduire sa taille à 8 octets (ou 4 octets pour le pointeur de fonction non membre), car l'espace réservé n'est rien de plus qu'un objet vide.

Ainsi, ce qui peut sembler être un simple gaspillage de réflexion pour seulement quelques octets peut réellement avoir un impact significatif sur les performances.

C'est la classe standard pour stocker une paire de valeurs. Il est retourné / utilisé par certaines fonctions standard, comme std::map::insert.

boost::compressed_pair prétend être plus efficace: voir ici

std :: pair est pratique pour quelques autres classes de conteneur de la STL.

Par exemple:

std::map<>
std::multimap<> 

Stocke std :: paires de clés et de valeurs.

Lors de l'utilisation de la carte et de la carte multiple, vous accédez souvent aux éléments à l'aide d'un pointeur sur une paire.

Informations supplémentaires: boost :: comprim_pair est utile lorsqu'un des types de la paire est une structure vide. Ceci est souvent utilisé dans la métaprogrammation des modèles lorsque les types de la paire sont déduits par programmation d'autres types. À la fin, vous avez généralement une forme de & "; Structure vide &";

.

Je préférerais std :: pair pour tout & "normal &"; utilisez, sauf si vous êtes dans la métaprogrammation de gabarit lourd.

Ce n’est rien mais une structure avec deux variables sous le capot.

Je n'aime pas utiliser std :: pair pour les retours de fonction. Le lecteur du code devrait savoir ce qu’il ya d’abord et ce qui est la deuxième.

Le compromis que j’utilise parfois est de créer immédiatement des références constantes à .first et .second, tout en nommant clairement les références.

  

À quoi sert std :: pair, pourquoi l'utiliser?

C’est aussi simple que deux éléments. Il a été défini dans la première version de STL à une époque où les compilateurs n'étaient pas largement compatibles. modèles et techniques de métaprogrammation nécessaires pour mettre en œuvre un type de tuple plus sophistiqué, comme Boost.Tuple .

Il est utile dans de nombreuses situations. std::pair est utilisé dans les conteneurs associatifs standard. Il peut être utilisé comme une simple forme d'étendue std::pair<iterator, iterator> - vous pouvez donc définir des algorithmes acceptant un seul objet représentant une étendue au lieu de deux itérateurs séparément. (C’est une alternative utile dans de nombreuses situations.)

Parfois, vous communiquez toujours deux informations, que ce soit sous forme de paramètre, de valeur de retour ou autre. Bien sûr, vous pouvez écrire votre propre objet, mais si ce ne sont que deux petites primitives ou similaires, parfois une paire semble très bien.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top