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 |
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.
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; }