¿Cómo funciona un vector como clave internamente en C ++?

14

Esta respuesta SO dice que el Mapa STL con un Vector para la Clave, el vector puede usarse como una clave. Entonces cuando usamos un vector como clave. ¿Cómo funciona eso realmente, ya que la clave debe ser única, de modo que cuando insertemos otro vector con los mismos elementos, la mapcomprobación de elementos duplicados por elemento o el nombre del vector especifica algo? Al igual que el nombre de la matriz representa la dirección base. Por lo tanto, una matriz se puede usar como una clave ya que la dirección base se puede usar como una clave en este caso, pero cuál es la clave en el caso de un vector. ¿Cómo funciona internamente?

Porque cuando imprimo el nombre del vector, obtengo un error

vector<int> v;
cout<<v; //error
Pulkit Bhatnagar
fuente
¿Qué quieres decir con imprimir el nombre del vector?
Bart
has operators == and <¿Cómo ayuda eso? mi pregunta era verificar que los elementos duplicados
mapearán el
3
@PulkitBhatnagar Pero ... Nadie te obligará a usar std::vectorcomo clave para std::map. Pagas por lo que usas . Se puede hacer, y tal vez hay algunos casos de uso para eso, pero ciertamente puede cambiar su estructura de datos de elección. Los contenedores STL están diseñados para ser lo más versátiles y utilizables de cualquier forma que el usuario quiera usar.
Yksisarvinen
1
@PulkitBhatnagar See, por ejemplo, ¿Por qué std :: map se implementa como un árbol rojo-negro? .
Daniel Langr
1
@PulkitBhatnagar Tiendas directamente. std::mapcopiará tanto la clave como el valor en sí mismo. std::unordered_mappuede almacenar hash de la clave.
Yksisarvinen

Respuestas:

9

Hay un operador sobrecargado <para la plantilla de clase std :: vector.

template <class T, 
class Allocator>
bool operator< (const vector<T, Allocator>& x, const vector<T, Allocator>& y);

eso se basa en el algoritmo estándar std::lexicographical_compare.

Aquí hay un programa demostrativo.

#include <iostream>
#include <iomanip>
#include <vector>
#include <iterator>
#include <algorithm>

int main() 
{
    std::vector<int> v1 = { 1, 2 };
    std::vector<int> v2 = { 1, 2, 3 };
    std::vector<int> v3 = { 2 };

    std::cout << std::boolalpha << ( v1 < v2 ) << '\n';
    std::cout << std::lexicographical_compare( std::begin( v1 ), std::end( v1 ),
                                               std::begin( v2 ), std::end( v2 ) )
             << '\n';                                              

    std::cout << std::boolalpha << ( v1 < v3 ) << '\n';
    std::cout << std::lexicographical_compare( std::begin( v1 ), std::end( v1 ),
                                               std::begin( v3 ), std::end( v3 ) )
             << '\n';                                              

    std::cout << std::boolalpha << ( v2 < v3 ) << '\n';
    std::cout << std::lexicographical_compare( std::begin( v2 ), std::end( v2 ),
                                               std::begin( v3 ), std::end( v3 ) )
             << '\n';                                              

    return 0;
}

Su salida es

true
true
true
true
true
true

Entonces la clase se puede usar como clave en el mapa.

Por defecto, el mapa de plantilla de clase usa el objeto de función std :: less que a su vez usa el operador <

template <class Key, class T, class Compare = less<Key>,
class Allocator = allocator<pair<const Key, T>>>
class map 
{
    //...
};

Sin embargo, no hay un operador sobrecargado << para la plantilla de clase std :: vector.

Vlad de Moscú
fuente
55
Veo sus respuestas recientemente en casi todas las preguntas de C ++ sobre SO, no sé si en toda mi vida podré lograr lo que tiene, pero haré lo mejor que pueda. Gracias por la respuesta
Pulkit Bhatnagar
8

El nombre de un objeto y el contenido de ese objeto son siempre cosas no relacionadas.

operator ==for std::vectorprimero comparará la longitud de los vectores y luego cada uno de sus elementos operator ==también.

operator <compara elementos en vector lexicográficamente, es decir, devuelve x[i] < y[i]el primer elemento no igual en vectores xy y.

Estos son los requisitos que std::maptiene para un tipo utilizado como Key. Como std::vectorsatisface a ambos, puede ser usado por as Key. Tenga en cuenta que el tipo administrado por vector también debe tener estos operadores sobrecargados para que esto funcione (porque std::vectordepende de esos operadores para implementar sus propios operadores).

Yksisarvinen
fuente