Operatore Virgola in C++

Concetti Chiave
  • L'operatore sizeof restituisce la dimensione, in byte, di un'espressione o di un nome di tipo.
  • sizeof è associativo a destra e restituisce un'espressione costante di tipo size_t.
  • sizeof non valuta il suo operando, rendendolo sicuro da usare con puntatori non validi.
  • La dimensione restituita da sizeof dipende dal tipo coinvolto, come char, puntatori, array e tipi di classe.
  • sizeof di un array restituisce la dimensione totale dell'array, non convertendolo in un puntatore.
  • Il risultato di sizeof può essere utilizzato per specificare la dimensione di un array.

Operatore Virgola

L'operatore virgola prende due operandi, che valuta da sinistra a destra. Come l'AND logico e l'OR logico e l'operatore condizionale, l'operatore virgola garantisce l'ordine in cui i suoi operandi vengono valutati.

L'espressione a sinistra viene valutata e il suo risultato viene scartato. Il risultato di un'espressione virgola è il valore del suo operando destro. Il risultato è un l-value se l'operando destro è un l-value.

Un uso comune per l'operatore virgola è in un ciclo for:

vector<int>::size_type cnt = ivec.size();
// assegna valori da size ... 1 agli elementi in ivec
for(vector<int>::size_type ix = 0;
        ix != ivec.size(); ++ix, --cnt)
    ivec[ix] = cnt;

Questo ciclo incrementa ix e decrementa cnt nell'espressione nell'intestazione del for. Sia ix che cnt vengono modificati ad ogni iterazione del ciclo. Finché il test di ix ha successo, impostiamo l'elemento corrente al valore corrente di cnt.

Esercizi

  • Il programma di sopra ha usato gli operatori di incremento e decremento prefissi. Spiega perché abbiamo usato il prefisso e non il postfisso. Quali cambiamenti dovrebbero essere fatti per usare le versioni postfisse? Riscrivi il programma usando operatori postfissi.

    Soluzione:

    Per capire meglio come funziona il programma di sopra, possiamo riscriverlo usando un ciclo while:

    vector<int>::size_type cnt = ivec.size();
    // assegna valori da size ... 1 agli elementi in ivec
    
    // Inizializzazione
    vector<int>::size_type ix = 0;
    
    while(ix != ivec.size()) {
        ivec[ix] = cnt;
        ++ix, --cnt;
    }
    

    Come si può osservare, in questo caso l'uso dell'operatore prefisso è completamente indifferente. Infatti, possiamo riscrivere l'ultima riga del ciclo while come segue:

    ix++, cnt--;
    

    In entrambi i casi, il risultato dell'operatore virgola è il valore di cnt-- o --cnt, che viene scartato. Quindi, in questo caso, non c'è differenza tra l'uso del prefisso o del postfisso. Tuttavia, l'uso del prefisso è generalmente preferito quando non è necessario il valore precedente, poiché può essere più efficiente per i tipi di dati complessi.

  • Spiega il seguente ciclo.

    constexpr int size = 5;
    int ia[size] = {1,2,3,4,5};
    for (int *ptr = ia, ix = 0;
                ix != size && ptr != ia+size;
                ++ix, ++ptr) { /* *...* */ }
    

    Soluzione:

    Questo ciclo for utilizza due variabili di controllo: un puntatore ptr che inizia all'inizio dell'array ia, e un indice ix che inizia da 0. La condizione del ciclo verifica che ix sia diverso da size (5) e che ptr non abbia raggiunto la fine dell'array (ia + size). Ad ogni iterazione, entrambi ix e ptr vengono incrementati. Questo permette di iterare attraverso l'array ia, con ptr che punta all'elemento corrente e ix che tiene traccia dell'indice corrente.

  • Usando la tabella degli operatori spiega cosa fa la seguente espressione:

    valore ? ++x, ++y : --x, --y
    

    Soluzione:

    La precedenza degli operatori determina l'ordine in cui le operazioni vengono eseguite in un'espressione. In questo caso, l'operatore condizionale ? : ha una precedenza più alta rispetto all'operatore virgola ,. Quindi, l'espressione viene valutata come:

    valore ? (++x, ++y) : (--x, --y)
    

    Se valore è vero, vengono eseguiti ++x e ++y, incrementando entrambi x e y e viene restituito il valore di ++y. Se valore è falso, vengono eseguiti --x e --y, decrementando entrambi x e y e viene restituito il valore di --y. In entrambi i casi, l'operatore virgola consente di eseguire due operazioni in sequenza, ma solo il risultato dell'ultima operazione viene restituito come risultato dell'intera espressione condizionale.