2010-08-31 22 views
20

Duplicar posible:
What is the difference between using a struct with two fields and a pair?struct con 2 celdas vs std :: pair?

Estimados todos,

tengo una pequeña pregunta sobre pares y estructura. ¿Hay alguna ventaja de usar un std :: pair en lugar de una estructura con dos celdas? he utilizado pares por un tiempo, pero el principal problema es la legibilidad: Si desea representar, por ejemplo, un binario (int "etiqueta", doble "valor") se puede utilizar un:

typedef std::pair<int,double> myElem; 

o un

typedef struct { 
    int label; 
    double value; 
} myElem; 

el código se vuelve más legible si sus declaraciones tienen un sentido "semántica" (que siempre sabe lo que es x.label. eso no es el caso con x.first).

Sin embargo, supongo que hay una ventaja con el par. ¿Es más eficiente o algo más?

+0

@KennyTM: Sí, lo siento. Me perdí este tema durante mi búsqueda. – ThR37

Respuesta

3

A pair se implementa como una plantilla de struct. Le proporciona una abreviatura para crear un par (típicamente heterogéneo). Además, hay algunas restricciones sobre los tipos que se pueden utilizar con un pair:

los requisitos Tipo

T1 y T2 deben ser tanto modelos de asignable. Las operaciones adicionales tienen requisitos adicionales . de par predeterminado constructor sólo puede utilizarse si tanto T1 y T2 son DefaultConstructible, operador == sólo puede utilizarse si ambos T1 y T2 son EqualityComparable, y operador < sólo puede utilizarse si ambos T1 y T2 son LessThanComparable .

(STL de SGI std::pair documentación)

Definir su propio POD puede tener sentido si los tipos no siguen ninguna de estas restricciones o si no se preocupan por ellos.

Finalmente, supongo que es una cuestión de elección personal/estilo de codificación.

4

Sin embargo, supongo que hay una ventaja con el par. ¿Es más eficiente o algo más?

Lo dudo, una instancia de std::pair es solo un struct, después de todo. std::pair viene con operator< definido, sin embargo. Pero eso no debería ser demasiado difícil de hacer por un struct con solo dos miembros.

Por lo general, lo hago como usted razonó: un struct con nombres de miembros dedicados es más fácil de leer que first y second.

2

Con std :: pair, puede usar los funtores de STL como select1st o select2nd. Asimismo, le permite usar otras funciones genéricas con su pareja, como el operador < y otros. Es cierto que con la llegada de boost/tr1, puedes lograr el mismo efecto usando bind.

Sin embargo, su punto sobre la legibilidad es muy cierto.

3

Su principal ventaja es que es genérico. Por ejemplo, cuando recupera algo de std::map, obtiene la clave y el valor asociado como primer y segundo elemento en un std::pair.

Del mismo modo, cuando usa std::equal_range para buscar un conjunto de valores iguales en una colección, obtiene iteradores al principio y al final del rango como el primer y segundo elemento en un std::pair.

Es difícil imaginar etiquetas significativas que se apliquen a ambos, por lo que se conformaron con una pareja que no significa mucho, pero que al menos no son engañosas. Usar 'clave' y 'datos' funcionaría para std::map, pero sería engañoso para std::equal_range (y si cambió a algo como lower_bound y para que sean más significativos para std::equal_range, sería igualmente incorrecto para los artículos en std::map).

+4

Solo mi opinión, pero no me gusta la elección que hicieron. una entrada de mapa debería haber sido (clave, valor) y un rango debería haber sido (inicio, fin). Ahora, estamos atrapados con tener que usar el sentido y engañoso (primero, segundo) en ambos casos. Y es difícil y no idiomático cambiar los nombres de campo. – stefaanv

12

En términos de rendimiento: es poco probable que cambie nada, solo está recubierto de azúcar.

En términos de facilidad de uso, prefiero utilizar una estructura personalizada, que puede ser declarado de esta manera (por cierto):

struct MyElement 
{ 
    int label; 
    double value; 
}; 

Soy un fuerte defensor de tipado fuerte, y yo preferiría una estructura "real" (y mejor aún, clase) que una tupla ad-hoc cuando es más que algo fugaz.

Principalmente porque:

  • Como se anotó first y second no tienen mucho que significa
  • No se puede agregar métodos/otros campos a una std::pair
  • No se puede agregar invariantes de clase a un std::pair

En general, realmente creo que el mantenimiento se beneficia al usar una estructura dedicada personalizada que una sola tupla de talla única.

Cuestiones relacionadas