Precedenza negli operatori C++
Gli operatori in cima alla lista sono valutati per primi. Gli operatori all'interno del gruppo hanno la stessa precedenza. Tutti gli operatori hanno asscociazione da sinistra a destra se non scritto diversamente.
\\
| Precedenza | Operatore | Descrizione | Esempio | Sovrascrivibile | Associazione | ||||
|---|---|---|---|---|---|---|---|---|---|
| 1 | :: | Operatore di scope resolution | Class::age = 2; | no | da sinistra a destra | ||||
| 2 | () | Chiamata di una funzione | printf("Hello world\n"); | SI | da sinistra a destra | ||||
| ::: | () | Inizializzazione di un membro | c_tor(int x, int y) : _x(x), _y(y * 10) {} | SI | ::: | ||||
| ::: | [] | Accesso ad un array | array[4] = 2; | SI | ::: | ||||
| ::: | %%->%% | Accesso ad un membro da un puntatore | %%ptr->age = 34;%% | SI | ::: | ||||
| ::: | . | Accesso ad un membro da un oggetto | obj.age = 34; | no | ::: | ||||
| ::: | ++ | Post-incremento | %%for (int i = 0; i < 10; i++) cout << i;%% | SI | ::: | ||||
| ::: | %%--%% | Post-decremento | %%for (int i = 10; i > 0; i--) cout << i;%% | SI | ::: | ||||
| ::: | dynamic_cast | Conversione di tipo runtime-checked | Y& y = dynamic_cast<Y&>(x); | no | ::: | ||||
| ::: | static_cast | Conversione di tipo unchecked | Y& y = static_cast<Y&>(x); | no | ::: | ||||
| ::: | reinterpret_cast | Conversione di tipo reinterpretata | int const* p = reinterpret_cast<int const*>(0x1234); | no | ::: | ||||
| ::: | const_cast | Cast away/Add constness | int* q = const_cast<int*>(p); | no | ::: | ||||
| ::: | typeid | Recuperare tipo variabile | std::type_info const& t = typeid(x); | no | ::: | ||||
| 3 | ! | Negazione logica | if (!done) %%...%% | SI | da destra a sinistra | ||||
| ::: | not | Forma alternativa per ! | ::: | ::: | ::: | ||||
| ::: | ~ | Complemento bit a bit | flags = ~flags; | SI | ::: | $ | |||
| ::: | compl | Forma alternativa per ~ | ::: | ::: | ::: | ||||
| ::: | ++ | Pre-incremento | %%for (i = 0; i < 10; ++i) cout << i;%% | SI | ::: | ||||
| ::: | %%--%% | Pre-decremento | %%for (i = 10; i > 0; --i) cout << i;%% | SI | ::: | ||||
| ::: | - | Riduzione di 1 | int i = -1; | SI | ::: | ||||
| ::: | + | Aggiunta di 1 | int i = +1; | SI | ::: | ||||
| ::: | * | Dereferenziazione | int data = *intPtr; | SI | ::: | ||||
| ::: | & | Indirizzo di... | int *intPtr = &data; | SI | ::: | ||||
| ::: | sizeof | Size del tipo dell'operando in bytes | size_t s = sizeof(int); | no | ::: | ||||
| ::: | new | Allocazione dinamica della memoria | long* pVar = new long; | SI | ::: | ||||
| ::: | new [] | Allocazione dinamica della memoria di un array | long* array = new long[20]; | SI | ::: | ||||
| ::: | delete | Deallocazione della memoria | delete pVar; | SI | ::: | ||||
| ::: | delete [] | Deallocazione della memoria di un array | delete [] array; | SI | ::: | ||||
| ::: | (type) | Cast verso un tipo specifico | int i = (int)floatNum; | SI | ::: | ||||
| 4 | %%->*%% | Selettore di un puntatore | %%ptr->*var = 24;%% | SI | da sinistra a destra | ||||
| ::: | .* | Selettore di un oggetto | obj.*var = 24; | no | ::: | ||||
| 5 | * | Moltiplicazione | int i = 2 * 4; | SI | da sinistra a destra | ||||
| ::: | / | Divisione | float f = 10.0 / 3.0; | SI | ::: | ||||
| ::: | % | Modulo | int rem = 4 % 3; | SI | ::: | ||||
| 6 | + | Addizione | int i = 2 + 3; | SI | da sinistra a destra | ||||
| ::: | - | Sottrazione | int i = 5 - 1; | SI | ::: | ||||
| 7 | %%<<%% | Shift di bit a sinistra | %%int flags = 33 << 1;%% | SI | da sinistra a destra | ||||
| ::: | %%>>%% | Shift di bit a destra | %%int flags = 33 >> 1;%% | SI | ::: | ||||
| 8 | < | Comparazione less-than | if (i < 42) %%...%% | SI | da sinistra a destra | ||||
| ::: | %%<=%% | Comparazione less-than-or-equal-to | %%if (i <= 42) ...%% | SI | ::: | ||||
| ::: | > | Comparazione greater-than | if (i > 42) %%...%% | SI | ::: | ||||
| ::: | %%>=%% | Comparazione greater-than-or-equal-to | %%if (i >= 42) ...%% | SI | ::: | ||||
| 9 | %%==%% | Comparazione equal-to | %%if (i == 42) ...%% | SI | da sinistra a destra | ||||
| ::: | eq | Forma alternativa per %%==%% | ::: | ::: | ::: | ||||
| ::: | != | Comparazione not-equal-to | if (i != 42) %%...%% | SI | ::: | ||||
| ::: | not_eq | Forma alternativa per != | ::: | ::: | ::: | ||||
| 10 | & | AND di bit | flags = flags & 42; | SI | da sinistra a destra | ||||
| ::: | bitand | Forma alternativa per & | ::: | ::: | ::: | ||||
| 11 | %% | %% | OR esclusivo di bit (XOR) | %%flags = flags | 42;%% | SI | da sinistra a destra | ||
| ::: | xor | Forma alternativa per %% | %% | ::: | ::: | ::: | |||
| 12 | %% | %% | OR inclusivo di bit | %%flags = flags | 42;%% | SI | da sinistra a destra | ||
| ::: | bitor | Forma alternativa per %% | %% | ::: | ::: | ::: | |||
| 13 | && | AND logico | if (conditionA && conditionB) %%...%% | SI | da sinistra a destra | ||||
| ::: | and | Forma alternativa per && | ::: | ::: | ::: | ||||
| 14 | %% | %% | OR logico | %%if (conditionA | conditionB) ...%% | SI | da sinistra a destra | ||
| ::: | or | Forma alternativa per %% | %% | ::: | ::: | ::: | |||
| 15 | ? : | Condizionale ternario (if-then-else) | int i = a > b ? a : b; | no | da destra a sinistra | ||||
| 16 | = | Operatore di assegnamento | int a = b; | SI | da destra a sinistra | ||||
| ::: | += | Incremento e assegnazione | a += 3; | SI | ::: | ||||
| ::: | -= | Decremento e assegnazione | b -= 4; | SI | ::: | ||||
| ::: | *= | Moltiplicazione e assegnazione | a *= 5; | SI | ::: | ||||
| ::: | /= | Divisione e assegnazione | a /= 2; | SI | ::: | ||||
| ::: | %= | Modulo e assegnazione | a %= 3; | SI | ::: | ||||
| ::: | &= | AND di bit e assegnazione | flags &= new_flags; | SI | ::: | ||||
| ::: | and_eq | Forma alternativa per &= | ::: | ::: | ::: | ||||
| ::: | %% | =%% | XOR di bit e assegnazione | %%flags | = new_flags;%% | SI | ::: | ||
| ::: | xor_eq | Forma alternativa per %% | =%% | ::: | ::: | ::: | |||
| ::: | %% | =%% | OR di bit e assegnazione | %%flags | = new_flags;%% | SI | ::: | ||
| ::: | or_eq | Forma alternativa per %% | =%% | ::: | ::: | ::: | |||
| ::: | %%<<=%% | Shift di bit a sinistra e assegnazione | %%flags <<= 2;%% | SI | ::: | ||||
| ::: | %%>>=%% | Shift di bit a destra e assegnazione | %%flags >>= 2;%% | SI | ::: | ||||
| 17 | throw | throw exception | throw EClass("Message"); | no | |||||
| 18 | , | Operatore di valutazione sequenziale | for (i = 0, j = 0; i < 10; i++, j++) %%...%% | SI | da sinistra a destra |
[modifica] Ordine di valutazione e side effect
Un aspetto importante del C++ in relazione alla precedenza degli operatori è l'ordine di valutazione e l'ordine dei side effect nelle espressioni. In molte circostanze l'ordine di come avvengono le cose non è specificato. Per esempio in f() + g() ,quale fra f() o g() è chiamato prima non è specificato. Se almeno una funzione ha side effect, il risultato può differire in funzione del compilatorem,delle differenti versioni dello stesso compilatore o fra diversi accessi allo stesso compilatore.
In più l'effetto di certe espressioni non è definita. Per esempio, considerando il codice seguente:
float x = 1; x = x / ++x;
Il valore di x e il resto del comportamento del programma dopo la valutazione dell'espressione non è definito. Il programma è semanticamente ill-formed: x è modificato doppiamente fra due punti consecutivi.
Espressioni come quella scritta sopra devono essere evitate. Quando c'è un dubbio, rompere l'espressione più grande in sotto-espressioni per assicurare che la valutazione sia corretta.
[modifica] Overloading degli operatori
L'overloading degli operatori può essere molto utile e molto pericoloso. Da una parte l'overload delgi operatori per una classe creata può aiutare il trasporto e la leggibilità del codice. Dall'altra parte si potrebbe sovraccaricare un operatore in modo da rendere offuscato o rovinare il proprio programma.Fai Attenzione! In particolare mai eseguire l'overload di &&, || o ,. Nel contesto overloaded si perde la garanzia che loperando sinistro sia valutato prima del secondo e che ci sia una sequenza di punti fra di loro.
Ci sono due modi per sovraccaricare un operatore: global function o class member.
Esempio di overloading con una global function:
ostream& operator <<(ostream& os, const myClass& rhs);
Ma per raggiungere qualsiasi dato private all'interno della classe definita dall'utente, si deve dichiarare la global function come friend all'interno della definizione della classe.
Esempio:
class myClass { // Gives the operator << function access to 'myData' // (this declaration should not go in public, private or protected) friend ostream& operator <<(ostream& lhs, const myClass& rhs); private: int myData; }
L'overloading con una classe può essere eseguito come segue:
class myClass { public: // The left hand side of this operator becomes '*this'. int operator +(const myClass& rhs); private: int myData; }