2010-11-29 19 views
6

De acuerdo con boost::tuple documentation, el acceso a un solo elemento de una tupla tiene el mismo rendimiento que el acceso a una variable miembro. Por ejemplo, dada la siguiente declaración:Boost tuple performance

tuple<A, B, C> t1(A(), B(), C()); 
struct T { A a; B b; C c; } 
T t2; 

Estas dos afirmaciones deben tener el mismo (o con una diferencia insignificante) rendimiento:

t1.get<2>(); 
t2.c; 

Miré en las fuentes de impulso :: tupla y, si ellos entendido bien (no estoy seguro de que hice), get<N> función en realidad realiza esta acción:

C get<2>(tuple<A, B, C>& t) 
{ 
    return t.tail.tail.head; 
    //Generally: return t.tail. <<N times>> .head; 
} 

esto es más similar a una consulta en una lista enlazada de un dir ect access, y, hasta donde yo entiendo, tiene O (N) complejidad en lugar de O (1), que se espera de un miembro de acceso. De mis experiencias pasadas con impulso, supongo que lo entendí mal; pero, ¿cuál es mi error? ¿Cómo funciona realmente get?

+4

Supongo que esto se basa en gran medida en la optimización del tiempo de compilación – Bwmat

Respuesta

6

Tiene razón sobre el rendimiento de la lista. Sin embargo, puede resolverse en tiempo de compilación y, por lo tanto, se reduce a O (1) en tiempo de ejecución. (Dado un compilador de optimización suficientemente bueno)

+0

Quiere decir, si recorro las "colas" en un ciclo for, se calcula el tiempo de ejecución, pero si solo escribo 't.tail.tail.tail. tail.tail.tail.tail.head' entonces los compiladores modernos pueden optimizarlo para un acceso directo al artículo final? ¿Hay alguna manera fácil de saber qué hace mi compilador con esto? – FireAphis

+0

¿Qué compiladores realmente realizan esa optimización? – Crashworks

+0

Un bucle puede ser tan bueno si el optimizador lo desenrolla correctamente. Tenga en cuenta que se trata de una estructura que es constante de tiempo de compilación aquí, no una estructura de datos dinámica ordinaria. – ltjax

3

Recuerde, en C++, el operador de punto no es una deferencia de puntero, es un cálculo de desplazamiento directo. La respuesta general es sí, i1.i2.i3.in para todo n es una operación de tiempo constante calculable en tiempo de compilación.

Si quiere aprender un poco sobre el compilador interno para esto sin cavar muy profundo, mire LLVM getelementptr http://llvm.org/docs/LangRef.html#i_getelementptr Esto es exactamente cómo un compilador de C++ como CLANG apuntaría a LLVM al compilar una referencia de estructura.