2012-06-13 11 views
5

Ho due domande correlate una generale e una specifica per il progetto su cui sto lavorando.loop, design della funzione ed efficienza: due domande

  1. In generale se ho un ciclo con un sacco di iterazioni (milioni), con alcune parti del codice eseguito in determinate condizioni, è meglio (più efficiente) per avere un ciclo con più istruzioni condizionali o cicli multipli senza loro. Per esempio.

Esempio 1:

while (something()) 
{ 
    // some common code 
    if (condition_a) 
     // some code 
    if (condition_b) 
     // some code 
    // some more common code 
} 

Esempio 2:

if (condition_a && condition_b) 
{ 
    while (something()) 
    { 
     // some common and specific code 
    } 
} 
else if (condition_a) 
    while (something()) //.. 
else if (condition_b) 
    // Another loop 
else //... 

Sembra esempio 2 comporterebbe codice più efficiente al costo di ridondanza perché le condizioni vengono controllate solo una volta anziché milioni di volte. Se il codice comune è enorme, o ci sono molte possibili condizioni, questo sembra estremamente ridondante.

  1. Ora al mio problema specifico. Ho una funzione che legge i punti da un file e li inserisce in una struttura dati. Sembra qualcosa di simile:

    mentre (lettore-> read_point) {// fare alcune cose // punto di inserimento }

Il problema è che ci sono diverse funzioni per la lettura di un punto che dovrebbe essere utilizzato in base ai criteri forniti dall'utente. Per esempio read_point_inside_circle(), read_point_inside_rectangle() ecc.

Idealmente mi piacerebbe utilizzare un puntatore a funzione per decidere in anticipo la funzione corretta, tuttavia non penso sia possibile poiché il lettore è un'istanza di una classe Reader (se è possibile in qualche modo risolverebbe tutti i miei problemi).

In questa situazione è meglio se ho cicli multipli che differiscono solo dalla condizione o dovrei usare più istruzioni if ​​per evitare codice ridondante, ad es.

for(;;) 
{ 
    if (read_every_point) 
     if(!reader->read_point()) 
      break; 
    else if (read_inside_circle) 
     if(!reader->read_inside_circle()) 
      break; 
    else if // ... 
} 
+2

Dubito che il primo avrà alcun effetto in qualsiasi compilatore moderno. Vorrei andare con ciò che è più leggibile e lasciare che il compilatore lo ottimizzi per me. – amit

risposta

2

Idealmente mi piacerebbe utilizzare un puntatore a funzione per decidere il corretto funzionamento in anticipo, ma non credo che sia possibile, in quanto il lettore è un'istanza di una classe Reader (se è possibile in qualche modo che risolverebbe tutti i miei problemi).

È possibile utilizzare puntatori a funzione membro per questo, supponendo che tutto il tuo leggere funzioni hanno la stessa firma:

typedef void (Reader::*read_fun_t)(); 
read_fun_t read_fun = &Reader::read_point; 
// or 
read_fun_t read_fun = &Reader::read_inside_circle; 

... 

(reader->*read_fun)(); 

o se non ci si sente confortevole con loro, basta creare la tua possedere funzioni gratuite che avvolgono il metodo chiamate:

void read_point(Reader* reader){ reader->read_point(); } 
void read_inside_circle(Reader* reader){ reader->read_inside_circle(); } 

e utilizzare invece i normali puntatori di funzione.

+0

Questo ha funzionato, ma purtroppo le mie funzioni assumono diversi parametri: read_point(), inside_circle (F64 center_x, F64 center_y, F64 radius), inside_rectangle (F64 min_x, F64 max_x, ...). Un modo per aggirare questo? – jaho

+0

@Marian: se i parametri sono _loop invariant_, verranno eseguiti oggetti e raccoglitori di funzioni di livello superiore. Cerca 'std | boost :: function' e' std | boost :: bind'. –

3

Per rispondere alla tua domanda specifica: il tempo necessario per leggere un file sta per sommergere il tempo trascorso in quello di if/else. Scrivi ciò che è più leggibile. Di solito è più efficiente e non lo ottimizzi finché non hai dimostrato che è un collo di bottiglia.

Per rispondere alla tua domanda generale: dipende da molte cose e i compilatori moderni sono molto bravi a fare le cose in modo efficiente indipendentemente dal tuo intuito. Quindi è una discussione teorica finché non si lavora codice su un compilatore e un'architettura specifici.