Contenedores de la biblioteca estándar de C++

La biblioteca estándar proporciona contenedores con seguridad de tipos para almacenar colecciones de objetos relacionados. Los contenedores son plantillas de clase. Cuando se declara una variable de contenedor, se especifica el tipo de los elementos que el contenedor va a contener. Los contenedores se pueden construir con las listas de inicializadores. Tienen funciones miembro para agregar y quitar elementos y realizar otras operaciones.

Itere sobre los elementos de un contenedor y obtenga acceso a los elementos individuales mediante iteradores. Puede usar iteradores explícitamente mediante sus funciones miembro, operadores y funciones globales. También puede usarlos de forma implícita, por ejemplo, mediante el uso de bucles de tipo range-for. Los iteradores para todos los contenedores de la biblioteca estándar de C++ tienen una interfaz común, pero cada contenedor define sus propios iteradores especializados.

Los contenedores se pueden dividir en tres categorías: contenedores de secuencias, contenedores asociativos y adaptadores de contenedor.

Contenedores de secuencias

Los contenedores de secuencias mantienen el orden de los elementos insertados que especifique.

Un contenedor de vector se comporta como una matriz, pero puede crecer automáticamente según sea necesario. Su acceso es aleatorio y se almacena de forma contigua, y su longitud es muy flexible. Por estas y otras razones, vector es el contenedor preferido de secuencias para la mayoría de las aplicaciones. Si no sabe con seguridad qué tipo de contenedor de secuencias debe utilizar, empiece usando un vector. Para obtener más información, vea vector Clase.

Un array contenedor tiene algunos de los puntos fuertes de , pero la longitud no es tan vector flexible. Para obtener más información, vea array Clase.

Un contenedor de deque (cola de dos extremos) permite inserciones y eliminaciones rápidas al principio y al final del contenedor. Comparte las ventajas de acceso aleatorio y longitud flexible de vector , pero no es contiguo. Para obtener más información, vea deque Clase.

Un contenedor es una lista vinculada doblemente que permite el acceso bidireccional, las inserciones rápidas y las eliminaciones rápidas en cualquier parte del contenedor, pero no se puede acceder aleatoriamente a un elemento del list contenedor. Para obtener más información, vea list Clase.

Un contenedor de forward_list es una lista vinculada única (la versión de acceso de avance de list). Para obtener más información, vea forward_list Clase.

Contenedores asociativos

En los contenedores asociativos, los elementos se insertan en un orden predefinido; por ejemplo, por orden ascendente. Los contenedores asociativos sin ordenar también están disponibles. Los contenedores asociativos se pueden agrupar en dos subconjuntos: asignaciones y conjuntos.

Una map, a la que a veces se hace referencia como un diccionario, consta de un par de clave/valor. La clave se utiliza para ordenar la secuencia, y el valor está asociado a esa clave. Por ejemplo, una map podría contener claves que representan cada palabra única en un texto y valores correspondientes que representan el número de veces que aparece cada palabra en el texto. La versión no ordenada de map es unordered_map. Para obtener más información, vea map Clase y unordered_map clase.

Un set es simplemente es un contenedor ascendente de elementos únicos (el valor también es la clave). La versión no ordenada de set es unordered_set. Para obtener más información, vea set Clase y unordered_set clase.

Tanto map como set permiten solo una instancia de una clave o elemento en el contenedor. Si se requieren varias instancias de elementos, utilice multimap o multiset. Las versiones no ordenadas son unordered_multimap y unordered_multiset. Para obtener más información, multimap vea Clase, unordered_multimap Clase, multiset Clasey unordered_multiset Clase.

Las asignaciones y los conjuntos no ordenados admiten iteradores bidireccionales, y los homólogos no ordenados admiten los iteradores hacia delante. Para obtener más información, consulta Iteradores.

Búsqueda heterogénea en contenedores asociativos (C++14)

Los contenedores asociativos ordenados (map, multimap, set y multiset) ahora admiten la búsqueda heterogéneo, lo que significa que ya no es necesario pasar exactamente el mismo tipo de objeto que la clave o elemento en funciones miembro como find() y lower_bound() . En vez de eso, puede pasar cualquier tipo para el que haya definida una sobrecarga operator< que permita la comparación con el tipo de clave.

La búsqueda heterogénea se debe habilitar expresamente al especificar el comparador "functor rombo" std::less<> o std::greater<> cuando se declara la variable de contenedor, como se muestra aquí:

std::set<BigObject, std::less<>> myNewSet;

Si usa el comparador predeterminado, el contenedor se comporta exactamente igual que en C++11 y versiones anteriores.

En el ejemplo siguiente se muestra cómo sobrecargar para permitir que los usuarios de realicen búsquedas simplemente pasando una cadena pequeña que se puede comparar con el miembro operator< std::set de cada BigObject::id objeto.

#include <set>
#include <string>
#include <iostream>
#include <functional>

using namespace std;

class BigObject
{
public:
    string id;
    explicit BigObject(const string& s) : id(s) {}
    bool operator< (const BigObject& other) const
    {
        return this->id < other.id;
    }

    // Other members....
};

inline bool operator<(const string& otherId, const BigObject& obj)
{
    return otherId < obj.id;
}

inline bool operator<(const BigObject& obj, const string& otherId)
{
    return obj.id < otherId;
}

int main()
{
    // Use C++14 brace-init syntax to invoke BigObject(string).
    // The s suffix invokes string ctor. It is a C++14 user-defined
    // literal defined in <string>
    BigObject b1{ "42F"s };
    BigObject b2{ "52F"s };
    BigObject b3{ "62F"s };
    set<BigObject, less<>> myNewSet; // C++14
    myNewSet.insert(b1);
    myNewSet.insert(b2);
    myNewSet.insert(b3);
    auto it = myNewSet.find(string("62F"));
    if (it != myNewSet.end())
        cout << "myNewSet element = " << it->id << endl;
    else
        cout << "element not found " << endl;

    // Keep console open in debug mode:
    cout << endl << "Press Enter to exit.";
    string s;
    getline(cin, s);
    return 0;
}

//Output: myNewSet element = 62F

Las siguientes funciones miembro de map, multimap, set y multiset se han sobrecargado para admitir la búsqueda heterogéneo:

  1. find

  2. count

  3. lower_bound

  4. upper_bound

  5. equal_range

Adaptadores de contenedor

Un adaptador de contenedor es una variación de un contenedor de secuencia o asociativo que restringe la interfaz para una mayor simplicidad y claridad. Los adaptadores de contenedor no admiten iteradores.

Un contenedor de queue sigue la semántica de FIFO (primero en entrar, primero en salir). El primer elemento insertado (es decir, insertado en la cola) es el primero en sacarse (es decir, en eliminarse de la cola). Para obtener más información, vea queue Clase.

Un contenedor de priority_queue se organiza de forma que el elemento que tiene el valor más alto siempre es el primero de la cola. Para obtener más información, vea priority_queue Clase.

Un contenedor de stack sigue la semántica de LIFO (último en entrar, primero en salir). El último elemento incrustado en la pila es el primer elemento sacado. Para obtener más información, vea stack Clase.

Dado que los adaptadores de contenedor no admiten iteradores, no se pueden usar con los algoritmos de la biblioteca estándar de C++. Para más información, vea Algoritmos.

Requisitos para los elementos de contenedor

Normalmente los elementos insertados en un contenedor de la biblioteca estándar de C++ pueden ser simplemente de cualquier tipo de objeto si se pueden copiar. Móvil (solo elementos): por ejemplo, los vector<unique_ptr<T>> creados mediante unique_ptr<> funcionarán siempre que no llame a funciones de miembro que intenten copiarlos.

No se permite al destructor iniciar una excepción.

Los contenedores asociativos ordenados (descritos anteriormente en este artículo) deben tener un operador de comparación público definido. (De forma predeterminada, el operador es operator<, pero se admiten incluso los que no funcionan con operator<).

Algunas operaciones en los contenedores también podrían requerir un constructor público predeterminado y un operador de equivalencia público. Por ejemplo, los contenedores asociativos sin ordenar requieren la compatibilidad de algoritmos hash y de igualdad.

Elementos contenedores de acceso

El acceso a los elementos de contenedores se realiza mediante iteradores. Para obtener más información, consulta Iteradores.

Nota

También se pueden usar bucles for basados en intervalos para recorrer en iteración colecciones de la biblioteca estándar de C++.

Comparar contenedores

Todos los contenedores sobrecargan el operador == para comparar dos contenedores del mismo tipo que tienen el mismo tipo de elemento. Puede usar == para comparar un vector con otro vector , pero no puede usarlo para comparar un vector con una lista o <string> un vector con un vector <string> <string> <string> <string> <char*> . En C++98/03, puede usar o para comparar tipos de contenedor o elementos no std::equal std::mismatch similares. En C++11, también puede usar std::is_permutation . Pero en todos estos casos, las funciones asumen que los contenedores tienen la misma longitud. Si el segundo intervalo es menor que el primero, se producirá un comportamiento indefinido. Si el segundo intervalo es más largo, los resultados pueden ser incorrectos porque la comparación no continúa más allá del final del primer intervalo.

Comparar contenedores diferentes (C++14)

En C++14 y versiones posteriores, puede comparar contenedores no similares o tipos de elementos diferentes mediante una de las sobrecargas de función , o que toman dos std::equal std::mismatch std::is_permutation intervalos completos. Estas sobrecargas le permiten comparar contenedores de distintas longitudes. Estas sobrecargas son mucho menos susceptibles a errores del usuario y están optimizadas para devolver false en tiempo constante cuando se comparan contenedores de longitudes diferentes. Por lo tanto, se recomienda usar estas sobrecargas a menos que tenga una razón clara para no hacerlo o esté usando un contenedor, que no se beneficia de las optimizaciones de std::list intervalo doble.

Vea también

Contenedores paralelos
<sample container>
Seguridad para subprocesos en la biblioteca estándar de C++