Qué es std:: pair?


¿Para qué sirve std::pair, por qué lo usaría y qué beneficios aporta boost::compressed_pair?

Author: ThiefMaster, 2008-09-19

10 answers

std::pair es un tipo de datos para agrupar dos valores como un solo objeto. std::map lo usa para pares clave y valor.

Mientras estás aprendiendo pair, usted puede comprobar hacia fuera tuple. Es como pair pero para agrupar un número arbitrario de valores. tuple es parte de TR1 y muchos compiladores ya lo incluyen con sus implementaciones de Bibliotecas Estándar.

También, revise el capítulo 1," Tuplas", del libro La Biblioteca Estándar de C++ Extensions: A Tutorial and Reference by Pete Becker, ISBN-13: 9780321412997, for a thorough explanation.

Texto alternativo http://ak.buy.com/db_assets/prod_images/225/202452225.jpg

 34
Author: jwfearn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-20 21:13:37

compressed_pair utiliza algunos trucos de plantilla para ahorrar espacio. En C++, un objeto (o pequeña) no puede tener la misma dirección que un objeto diferente.

Así que incluso si tienes

struct A { };

A's tamaño no será 0, porque entonces:

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

Aguantaría, lo cual no está permitido.

Pero muchos compiladores harán lo que se llama la "optimización de clases base vacías":

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

Aquí, está bien que B y C tengan el mismo tamaño, incluso si sizeof(A) no puede ser cero.

Así que boost::compressed_pair aprovecha esta optimización y, cuando sea posible, heredará de uno u otro de los tipos en el par si está vacío.

Así que un std::pair podría parecer (He elided un buen acuerdo, ctors etc.):

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

Eso significa que si FirstType o SecondType es A, su pair<A, int> tiene que ser mayor que sizeof(int).

Pero si usas compressed_pair, su código generado se verá similar a:

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

Y compressed_pair<A,int> solo será tan grande como sizeof(int).

 80
Author: Logan Capaldo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-13 02:22:15

A veces necesita devolver 2 valores de una función, y a menudo es excesivo ir y crear una clase solo para eso.

Std:pair es muy útil en esos casos.

Creo que boost:compressed_pair es capaz de optimizar los miembros de tamaño 0. Que es sobre todo útil para la maquinaria pesada de la plantilla en bibliotecas.

Si controlas los tipos directamente, es irrelevante.

 11
Author: David Pierre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 23:21:37

Puede sonar extraño escuchar que compressed_pair se preocupa por un par de bytes. Pero en realidad puede ser importante cuando se considera dónde se puede usar compressed_pair. Por ejemplo, consideremos este código:

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

De repente puede tener un gran impacto usar compressed_pair en casos como el anterior. ¿Qué podría pasar si boost::bind almacena el puntero de la función y el lugar-holder _1 como miembros en sí mismo o en un std::pair en sí mismo? Bueno, podría hincharse hasta sizeof(&f) + sizeof(_1). Asumiendo una función el puntero tiene 8 bytes (no es raro especialmente para las funciones miembro) y el marcador de posición tiene un byte (vea la respuesta de Logan para saber por qué), entonces podríamos haber necesitado 9 bytes para el objeto bind. Debido a la alineación, esto podría inflar hasta 12 bytes en un sistema habitual de 32 bits.

boost::function anima a sus implementaciones a aplicar una optimización de objetos pequeños. Esto significa que para functores pequeños, se utiliza un pequeño búfer directamente incrustado en el objeto boost::function para almacenar el funtor. Para más grande funtores, el montón tendría que ser utilizado mediante el uso de operador nuevo para obtener memoria. Alrededor de boost versión 1.34, se decidió adoptar esta optimización, porque se suponía que uno podría obtener algunos beneficios de rendimiento muy grandes.

Ahora, un límite razonable (aún, quizás todavía bastante pequeño) para un búfer tan pequeño sería de 8 bytes. Es decir, nuestro objeto bind bastante simple no encajaría en el búfer pequeño, y requeriría que el operador new se almacenara. Si el bind object above usaría un compressed_pair, en realidad puede reducir su tamaño a 8 bytes (o 4 bytes para el puntero de función no miembro a menudo), porque el marcador de posición no es más que un objeto vacío.

Por lo tanto, lo que puede parecer simplemente desperdiciar mucho pensamiento por solo unos pocos bytes en realidad puede tener un impacto significativo en el rendimiento.

 11
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 19:35:32

Es la clase estándar para almacenar un par de valores. Es devuelto / usado por algunas funciones estándar, como std::map::insert.

boost::compressed_pair dice ser más eficiente: ver aquí

 3
Author: user17481,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 23:46:59

Std::pair es útil para un par de las otras clases de contenedores en el STL.

Por ejemplo:

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

Ambos almacenan pares de claves y valores std::.

Cuando se utiliza el mapa y multimap, a menudo se accede a los elementos utilizando un puntero a un par.

 3
Author: John Mulder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 00:00:36

Información adicional: boost::compressed_pair es útil cuando uno de los tipos del par es una estructura vacía. Esto se usa a menudo en la metaprogramación de plantillas cuando los tipos del par se deducen programáticamente de otros tipos. Al final, por lo general tiene alguna forma de "estructura vacía".

Preferiría std::pair para cualquier uso "normal", a menos que esté en metaprogramación de plantillas pesadas.

 3
Author: rlerallut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-23 11:48:18

No es más que una estructura con dos variables bajo el capó.

En realidad no me gusta usar std::pair para retornos de funciones. El lector del código tendría que saber qué .primero es y qué .el segundo es.

El compromiso que uso a veces es crear inmediatamente referencias constantes a .primero y .segundo, nombrando claramente las referencias.

 3
Author: Andrei Taranchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-22 04:54:53

¿Para qué sirve std:: pair, por qué lo usaría?

Es igual de simple la tupla de dos elementos. Se definió en la primera versión de STL en tiempos en que los compiladores no soportaban ampliamente las plantillas y las técnicas de metaprogramación que serían necesarias para implementar un tipo más sofisticado de tupla como Boost.Tupla.

Es útil en muchas situaciones. std::pair se utiliza en contenedores asociativos estándar. Se puede utilizar como una forma simple de rango std::pair<iterator, iterator> - así que uno puede definir algoritmos que aceptan un solo objeto que representa el rango en lugar de dos iteradores por separado. (Es una alternativa útil en muchas situaciones.)

 2
Author: mloskot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-21 17:42:57

A veces hay dos piezas de información que siempre se pasan juntas, ya sea como un parámetro, o un valor devuelto, o lo que sea. Claro, podrías escribir tu propio objeto, pero si son solo dos primitivas pequeñas o similares, a veces un par parece estar bien.

 1
Author: Aaron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 23:26:45