2012-07-06 9 views
11

Variante a:¿Las comparaciones entre iterator y const_iterator son ineficaces?

const auto end = whatever.end(); 
for (auto it = whatever.begin(); it != end; ++it) 
{ 
    // ... 
} 

Variante B:

const auto end = whatever.cend(); // note the call to cend insteand of end here 
for (auto it = whatever.begin(); it != end; ++it) 
{ 
    // ... 
} 

¿Hay alguna razón para creer que la variante b será menos eficiente que la variante a, ya que la condición del bucle compara dos tipos diferentes de iteradores? ¿Esto causa una conversión implícita en it?

(end se utiliza varias veces dentro del bucle, de ahí mi deseo de izar a cabo.)

+0

¿Para qué contenedor? –

+0

@David En mi caso específico, es un 'std :: string', pero tengo curiosidad en general. – fredoverflow

Respuesta

12

En principio, podría ser menos eficiente y resultar en una conversión implícita con el coste distinto de cero.

En la práctica, iterator y const_iterator son propensos a participar en una relación de herencia (ya sea una deriva de la otra, o ambas se derivan de un _iterator_base) de tal manera que el operador de la desigualdad se define en la clase base y no hay necesidad de una conversión implícita (en cambio, el iterador derivado es ignorado). Incluso en ausencia de estos, es probable que la conversión sea lo suficientemente trivial como para incluirla y optimizarla.

libstdC++ optimiza estas comparaciones de manera diferente, mediante la definición de operator== y operator!= entre iterator y const_iterator: http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a02037.html#l00295

libC++ no tiene ninguna optimización: http://llvm.org/svn/llvm-project/libcxx/trunk/include/__tree - aunque de nuevo el constructor de const_iterator de iterator es tan trivial que había espero que esté completamente optimizado.

Cuestiones relacionadas