Traduzioni di questa pagina?:

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 bitflags = 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

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.

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