2015-03-23 14 views
5

Così come io so, ci sono due modi per accedere elemento di array in C++:diversi modi per accedere elemento dell'array

int array[5]; //If we have an array of 5 integers 

1) Utilizzando le parentesi quadre

array[i]

2) Utilizzo dei puntatori

*(array+i) 

L'insegnante della mia università mi obbliga a usare il metodo *(array+i), dicendomi che "è più ottimizzato".

Quindi, puoi spiegare, c'è una vera differenza tra loro? Il secondo metodo ha qualche vantaggio rispetto al primo?

+6

Sarei estremamente preoccupato per le altre cose che il tuo professore universitario ti dirà, se già per le cose di base egli fa affermazioni del genere! La seconda versione come il chiaro vantaggio di offuscare il tuo codice senza ulteriore sforzo – Christophe

+0

_ @E_Tony_ Puoi chiarire il tipo di elemento dell'array concreto in questione per favore? –

+1

Ben fatto per chiederlo. –

risposta

11

È un'opzione più ottimizzata rispetto all'altra?

Bene, vediamo, in pratica, il codice assembler generato con MSVC2013 (non ottimizzato la modalità di debug):

; 21 : array[i] = 8; 

    mov eax, DWORD PTR _i$[ebp] 
    mov DWORD PTR _array$[ebp+eax*4], 8 

; 22 : *(array + i) = 8; 

    mov eax, DWORD PTR _i$[ebp] 
    mov DWORD PTR _array$[ebp+eax*4], 8 

Bene, con tutta la buona volontà, non riesco a vedere alcuna differenza nel codice generato.

A proposito, qualcuno ha scritto di recente su SO: l'ottimizzazione prematura è la radice di tutti i mali. Il tuo insegnante dovrebbe saperlo!

Uno ha un vantaggio rispetto all'altro?

Chiaramente, l'opzione uno ha il vantaggio di essere intuitiva e leggibile. Option2 diventa rapidamente UNREADABLE in applicazioni matematiche.

Esempio 1: distanza di un vettore matematico 2D implementato come una matrice.

double v[2] = { 2.0, 1.0 }; 

// option 1: 
double d1 = sqrt(v[0] * v[0] + v[1] * v[1]); 

//option 2: 
double d2 = sqrt(*v**v + *(v + 1)**(v + 1)); 

In effetti, la seconda opzione è davvero fuorviante a causa della **, perché si deve leggere attentamente la formula per capire se si tratta di un doppio dereference o di una moltiplicazione per un puntatore Dereferenced. Non si parla di persone che potrebbero trarre in inganno da alcuni altri linguaggi come ADA in cui ** significa 2 "potere"

Esempio: calcolo del determinant di una matrice 2x2

double m[2][2] = { { 1.0, 2.0 }, { 3.0, 4.0 } }; 

// option 1 
double dt1 = m[0][0] * m[1][1] - m[1][0] * m[0][1]; 

// option 2 
double *x = reinterpret_cast<double*>(m); 
double dt2 = *x **(x+2*1+1) - *(x+2*1) * *(x+1); 

Con Arays multidimensionali, opzione 2 è un incubo. Si noti che:

  • ho usato una temporanea un puntatore tridimensionale x essere in grado di utilizzare la formula. L'utilizzo di m qui avrebbe causato messaggi di errore di compilazione fuorvianti.

  • devi conoscere il layout preciso del tuo oggetto e devi introdurre la dimensione della prima dimensione in ogni formula!

Immagina che in seguito desideri aumentare il numero di elementi nel tuo array 2D. Dovrai riscrivere tutto!

gap semantico

Che cosa il vostro insegnante non è presente qui, è che l'operatore [] ha un significato che è ben compreso dal compilatore e il lettore. È un'astrazione che non dipende da come la struttura dei dati viene implementata nella realtà.

Supponiamo di avere un array e un codice molto semplice:

int w[10] {0}; 
... // put something in w 
int sum = 0; 
for (int i = 0; i < 10; i++) 
    sum += w[i]; 

In seguito si decide di utilizzare un std::vector al posto di un array, in quanto si è appreso che è molto più flessibile e potente. Tutto quello che dovete fare è cambiare la definizione (e inizializzazione) di w:

vector<int> w(10,0); 

Il resto del codice funzionerà, perché la semantica del [] è la stessa per i due strutures dati. Vi lascio immaginare cosa sarebbe hapened se avresti usato il consiglio del tuo insegnante ...

+1

Non è qualcosa che "qualcuno ha scritto di recente su SO". È ** [una famosa citazione di Donald Knuth] (http://c2.com/cgi/wiki?PrematureOptimization) ** – sehe

+0

@sehe grazie per il riferimento ;-) Il mio preferito è "Non usare il codice, trova meglio Algoritmi "di BW Kernighan – Christophe

9

"maestra di mia università mi costringe a usare *(array+i) metodo, che mi diceva che 'è più ottimizzato'."

Cosa stanno dicendo per favore? Se non hai trovato qualcosa di completamente sbagliato in questa affermazione , chiedi loro una prova riguardante il codice assemblatore generato (@Christophe ne forniva uno in his answer qui). Non credo che potrebbero darti questo, quando guardi più in profondità.

Si potrebbe facilmente verificare questo te stesso utilizzando il e.g. il -S option di GCC per produrre il codice assembler e confrontare i risultati ottenuti con l'una o l'altra versione.

Qualsiasi compilatore C++ decente e moderno produrrà lo stesso codice assembler per entrambe le affermazioni, a condizione che si riferiscano a qualsiasi c++ fundamental types.

"Il secondo metodo presenta vantaggi rispetto al primo?"

No. Il contrario sembra verificarsi, a causa della leggibilità meno intuitiva del codice.


1) Per class/struct tipi ci potrebbero essere sovraccarichi del T& operator[](int index) che fare le cose dietro le quinte, ma se è così, *(array+i) dovrebbero essere attuate a comportarsi in modo coerente.

+0

'Qualsiasi compilatore C++ moderno e dignitoso produrrà lo stesso codice assemblatore per entrambe le affermazioni. Sì, il compilatore dovrebbe ottimizzarlo per te indipendentemente da come lo scrivi , a meno che tu non spenga completamente l'ottimizzazione Personalmente, per me usa la parentesi quadra è più leggibile – DigitalNinja

+0

@BinaryJudy No! Anche con l'ottimizzazione disattivata, cosa dovrebbe esserci per ottimizzare ulteriormente? –

+0

Ha, stavo proprio leggendo e ho capito che è sbagliato. Il codice assemblato sarà lo stesso per entrambi * * (array + i) 'e' array [i] 'indipendentemente dall'ottimizzazione. – DigitalNinja

7

insegnante di mia università mi costringe a usare *(array+i) metodo, che mi diceva che "è più ottimizzato".

Il tuo insegnante è assolutamente sbagliato.

Lo standard definisce array[i] equivale a *(array+i) e non c'è motivo per un compilatore di trattarli diversamente. Loro sono la stessa cosa. Né sarà "più ottimizzato" rispetto all'altro.

L'unico motivo per raccomandare l'uno sull'altro è la convenzione e la leggibilità e, in quelle competizioni, vince array[i].

Mi chiedo cos'altro si sta sbagliando il tuo insegnante? :(

+0

_" Mi chiedo in che altro modo il tuo insegnante si stia sbagliando? :("_ Il vecchio _" Il cieco che guida lo zoppo "_ problema. –

Problemi correlati