2009-07-11 11 views

Respuesta

65

Recuperar un elemento por índice es una operación O (n) para la lista vinculada, que es lo que std::list es. Por lo tanto, se decidió que sería proporcionar operator[] engañosa, ya que las personas se verían tentados a utilizar activamente, y luego se vería código como:

std::list<int> xs; 
for (int i = 0; i < xs.size(); ++i) { 
    int x = xs[i]; 
    ... 
} 

que es O (n^2) - muy desagradable. Por lo tanto, el estándar ISO C++ menciona específicamente que todas las secuencias STL que admiten operator[] deben hacerlo en tiempo constante amortizado (23.1.1 [lib.sequence.reqmts]/12), que se puede alcanzar para vector y deque, pero no list.

Para los casos en que realmente necesita ese tipo de cosas, puede utilizar std::advance algoritmo:

int iter = xs.begin(); 
std::advance(iter, i); 
int x = *iter; 
+0

Entonces, básicamente, ¿solo se trata de evitar que la gente cometa errores? –

+17

sí.O de no hacer promesas que no puedes cumplir. En el STL, el operador [] promete * acceso * eficiente a elementos arbitrarios. – jalf

+0

¡Y gracias Pavel por la referencia estándar de C++! –

3

No sería demasiado difícil (para el implementador) pero sería demasiado difícil en tiempo de ejecución, ya que el rendimiento será terrible en la mayoría de los casos. Obligar al usuario a ir a través de cada enlace hará que sea más obvio lo que está sucediendo ahí que 'myList [102452]' lo haría.

+0

Para elaborar un operador de bit [] es una operación de tiempo constante en todos los demás lugares donde se usa. Dar el mismo nombre a una operación O (n) sería inconsistente y confuso. – dmckee

+0

Bueno, es O (log n) en un mapa, pero entiendo su punto. –

+0

En un mapa, definitivamente no es un índice posicional, lo cual es bastante obvio, excepto quizás cuando la clave del mapa es un número entero, pero si confunde el acceso posicional con la búsqueda de claves, ya tiene problemas mucho mayores;) –

1

Creo que he encontrado la respuesta en otro SO publicar Extending std::list

"su operador [] es O (N) time "- este es exactamente el motivo por el cual no está incluido en estándar del estándar <>. - Michael Burr 14 de diciembre a las 17:29

Aún así, ¿es esa la única razón?

EDITAR: Parece que, como las personas lo mencionaron, es más una cuestión de consistencia con respecto al rendimiento que estrictamente al rendimiento.

+0

¿Quiere decir que no es razón suficiente? :-) –

+0

Lo es. Buscando en otra parte, .NET 'LinkedList' no proporciona un indexador por las mismas razones, es demasiado engañoso. Tradicionalmente, cuando algo tiene un indexador posicional, se supone que la operación es O (1). –

0

En realidad, no hay absolutamente ninguna razón para no proporcionar el operador [] o, al menos, método al (int), debido a las dos razones:

  • Es lista doblemente enlazada, por lo que necesita para moverse en la mayoría del tamaño()/2 coloca su iterador para obtener su índice, y los costos para mantener internamente pocos iteradores fijos más son muy bajos. Y al final, la biblioteca de Qt proporciona el operador [] y el at, y no veo el costo de rendimiento al usarlo.
  • obligar a las personas a no usar es un hábito de programación muy malo, porque una lista será un contenedor muy útil, si tiene un "acceso aleatorio" cerca del acceso vinculado, hay una variedad de ejemplos cuando necesita ambos accesos, dependiendo de qué punto de tiempo de ejecución.
+0

¿Es esto puramente base en su opinión o ha creado un buen escenario de prueba, donde muestra que su implementación personalizada de 'std :: list :: operator []' es eficiente? (Por cierto, de acuerdo con Stroustrup, el contenedor estándar que debe usar es 'std :: vector'). – Zeta

Cuestiones relacionadas