2010-10-05 36 views
26

Supongamos que tengo un std::vector dicen VectorComprobación de si un vector está vacío

Ahora después de realizar algunas operaciones sobre el vector (ya sea inserción o deleción) Quiero comprobar si el vector está vacío y sobre la base de que yo quiero realizar algunas operaciones.

¿Qué enfoque es mejor

Enfoque 1

if (Vector.size() == 0){ /* operations */ } 

Enfoque 2

if (Vector.empty()) { /* operations */ } 

¿Qué es un mejor enfoque, 1 o 2?

+0

https://stackoverflow.com/questions/743197/size-vs-empty-in-vector-why-empty-is-preferred – x29a

Respuesta

6

El enfoque (2) sería mejor porque empty() siempre se ejecuta en un tiempo constante [es decir O(1)] independientemente del tipo de contenedor.

size() también se ejecuta en O(1) [para std :: vector] aunque podría funcionar en O(n) para std:list [esa es la aplicación definida para ser honesto]

En Effective STL [Artículo 4] Scott Meyers dice

Debería preferir el constructo usando vacío, y el motivo es simple: el vacío es una operación de tiempo constante para todos los contenedores estándar, pero para algunas implementaciones de listas, el tamaño lleva tiempo lineal.

.....

Pase lo que pase, no se puede ir mal si se llama vacío en vez de comprobar a ver si size() == 0. Así que llame a vacío cada vez que necesita saber si un contenedor tiene cero elementos.

+3

No, 'size()' está garantizado como O (1) , especialmente para 'vector'. En C++ 0x, se requerirá que 'size()' sea O (1) para cualquier contenedor que lo implemente. –

+0

@James: ¿para listas también? – sbi

+1

@sbi: Sí; todos los contenedores. Actualmente, los requisitos del contenedor solo dicen que 'size()' _ debe tener una complejidad de tiempo constante (lo que significa que no hay ningún requisito de complejidad en absoluto). C++ 0x cambia eso. Sin embargo, me equivoqué en mi primer comentario cuando dije "por cualquier contenedor que lo implemente"; todos los contenedores deben implementar 'size()'. –

8

Yo diría approch no 2, como el método empty() fue intencionalmente diseñado para comprobar si un vector está vacío. También puede verificar la eficiencia de ambos enfoques y luego decidir cuál es mejor.

+4

El método 'empty' es particularmente bueno para' std :: list's porque el cálculo de su tamaño puede ser muy ....... largo. – Benoit

+1

@Benoit: algunas implementaciones de 'list' tienen un tiempo constante' size() '; en C++ 0x, se requerirá que 'size()' tenga una complejidad de tiempo constante para todos los contenedores, incluida 'list'. –

+0

@James: Cuál es una buena razón para usar una 'lista' personalizada o de un tercero, si usa 'empalme' y quiere * * que sea de tiempo constante. Luego, vuelve a tener 'my_list :: size' como O (N). – Potatoswatter

2

Si es nuevo en la programación, use uno que tenga más significado para usted. Por ejemplo, si == 0 es más significativo para usted que .empty(), úselo.

Más tarde, si tiene problemas de rendimiento (que dudo mucho que tenga aquí) utilice uno que satisfaga sus objetivos de rendimiento.

+5

Prefiero que mis compañeros de trabajo, novatos o no, utilicen el que tiene más significado para los programadores experimentados. Todos tendremos experiencia en algún momento, después de todo. – sbi

+0

@sbi: No solo eso, sino el que es mejor para el rendimiento a largo plazo (por ejemplo, si cambia de un 'std :: vector' a un' std :: list' en el futuro). –

+0

@sbi: tiene su punto allí; sin embargo, el código es difícil de leer, tiene que facilitarlo aquí y ahora. –

30

v.size() == 0 dice "Estoy comparando el tamaño", pero lo hace para comprobar si el contenedor está vacío. Hay un pequeño algoritmo para digerir (muy pequeño, ya que solo consiste en una comparación) antes de saber qué hace.
OTOH, v.empty() hace exactamente lo que dice: comprueba si v está vacío.
Debido a esto, claramente prefiero el # 2, ya que hace lo que dice. Es por eso que se inventó empty(), después de todo.

Pero también hay una razón para preferir algorítmica empty(): Si alguien más adelante cambia std::vector en un std::list, v.size()fuerza tienen O (n). (En C++ 03 está garantizado que ser O (1) para std::vector, pero no para std::list. De acuerdo a los comentarios de James para Prasoon's answer será O (1) para todos contenedores en C++ 1x.)

+1

En respuesta a su pregunta/comentario a continuación, Howard Hinnant redactó un documento técnico sobre las compensaciones para 'list' (en realidad es un empalme() - velocidad vs. tamaño() - compensación de velocidad). Parece que no puedo acceder al documento en este momento, pero [Michael Burr lo resumió]. (Http://stackoverflow.com/questions/228908/is-listsize-really-on/228914#228914). –

+0

@James: ¡Gracias! – sbi

+0

¿Qué es C++ 1x? : - | – Donotalo

3

Normalmente, un vector se implementa internamente como un puntero a una matriz asignada dinámicamente, y los miembros de datos que contienen el capacity y size del vector. El size del vector es la cantidad real de elementos, mientras que la capacidad se refiere al tamaño de la matriz dinámica.

Dada esta implementación, la función de miembro size() simplemente será un getter para el miembro size.

El empty() devolverá el resultado de la comparación size == 0.

Ambos son igualmente eficientes O(1) pero se recomienda a empty() si desea comprobar si el vector está vacío. Porque para eso está la función. Hará que su código sea más fácil de leer.

-1

Ir por vacío().

+0

(dis) me gusta su razonamiento para su opinión. – sbi

+1

No debería haber tanto alboroto sobre el vacío sobre el tamaño para el vector ¿no? : D – nakiya

1

Sólo por diversión: ¿por qué no:

if(Vector.begin() == Vector.end()) 

?

1

En realidad vector.empty() y vector.size() == 0 están haciendo lo mismo. vacío compara el principio y el final y devuelve verdadero si son iguales, el tamaño calcula begin - end para devolver 0 si está vacío y hace lo mismo con otro cálculo.

+0

Disculpe, ¿puede reformular su respuesta? Es difícil de entender, intente separar las oraciones y explíqueme por qué una es igual a la otra. – Armfoot