Costanza costante nei ritorni di sovraccarico dell'operatore C ++
-
08-07-2019 - |
Domanda
Sono un po 'confuso sul perché mi è stato detto di restituire const foo da un operatore binario in c ++ anziché solo foo.
Ho letto "Pensando in C ++" di Bruce Eckel, e nel capitolo sul sovraccarico dell'operatore, dice che "facendo il valore di ritorno [di un operatore binario con sovraccarico] const, tu affermare che è possibile chiamare solo una funzione membro const per quel valore di ritorno. Ciò è corretto, perché ti impedisce di archiviare informazioni potenzialmente preziose in un oggetto che molto probabilmente andranno perse " ;.
Tuttavia, se ho un operatore positivo che restituisce const e un operatore incremento prefisso, questo codice non è valido:
class Integer{
int i;
public:
Integer(int ii): i(ii){ }
Integer(Integer&);
const Integer operator+();
Integer operator++();
};
int main(){
Integer a(0);
Integer b(1);
Integer c( ++(a + b));
}
Per consentire questo tipo di assegnazione, non avrebbe senso che l'operatore + restituisca un valore non const? Questo potrebbe essere fatto aggiungendo const_casts, ma diventa piuttosto voluminoso, vero?
Grazie!
Soluzione
Quando dici ++ x, stai dicendo " aggiungi 1 a x, memorizza il risultato in xe dimmi che cosa era " ;. Questo è l'operatore di preincremento. Ma, in ++ (a + b), come dovresti "salvare il risultato in a + b " ;?
Certamente potresti salvare il risultato nel temporaneo che attualmente contiene il risultato di a + b, che svanirebbe abbastanza presto. Ma se non ti importava davvero dove fosse archiviato il risultato, perché lo hai incrementato invece di aggiungerne solo uno?
Altri suggerimenti
FYI, ++ (a + b)
è illegale anche con i POD (semplici vecchi tipi di dati, come int
). Quindi ha senso non consentirlo nemmeno per i tuoi tipi di classe. Prova questo:
int a = 1;
int b = 2;
int c = ++(a+b);
GCC restituisce l'errore : lvalue richiesto come operando di incremento
.
Nel tuo caso, sarebbe preferibile che il tuo costruttore di copie prendesse un argomento const Integer
e crea invece il tuo Integer c
come questo:
Integer c(a + b + Integer(1));
I costruttori di copie di solito prendono un riferimento const , risolvendo il problema per te.
(Avere un copiatrice non const implica un trasferimento di risorse, che a volte può essere utile, ma per il 99% di tutte le situazioni, non è necessario)
Credo che l'esempio di OP sarebbe adatto alla domanda se l'operatore addizione viene sostituito con qualsiasi altro operatore binario che restituisce un riferimento, ad esempio un operatore di assegnazione:
Integer c( ++(a = b));
Sono venuto qui chiedendomi se il mio operatore di assegnazione dovrebbe restituire un riferimento const o non const. Alcuni tutorial usa versioni non costanti, contrariamente a "Pensare nei consigli di C ++". E alcuni altri riferimenti forniscono un ragionamento dietro ciò:
Si noti che il riferimento restituito non è dichiarato const. Questo può essere un po 'confuso, perché ti permette di scrivere cose folli come questa:
MyClass a, b, c;
...
(a = b) = c; // Cosa ??
A prima vista, potresti voler evitare situazioni come questa, avendo operator = restituisce un riferimento const. Tuttavia, affermazioni come questa funzioneranno con tipi primitivi. E, peggio ancora, alcuni strumenti si basano su questo comportamento. Pertanto, è importante restituire un riferimento non const dal proprio operatore =. La regola empirica è, "Se è abbastanza buono per gli ints, è abbastanza buono per i tipi di dati definiti dall'utente."