In diversi posti che ho visto le firme raccomandati di copiare e spostare i costruttori dato come:Un costruttore di spostamenti deve prendere un riferimento const o non const?
struct T
{
T();
T(const T& other);
T(T&& other);
};
Dove il costruttore di copia prende un riferimento const, e il costruttore mossa prende un riferimento rvalue non-const.
Per quanto posso vedere, però, questo impedisce mi approfittando della semantica mossa quando il ritorno oggetti const da una funzione, come ad esempio nel caso di seguito:
T generate_t()
{
const T t;
return t;
}
Testing questo con VC11 Beta, T
' Viene chiamato il costruttore di copie s e non il costruttore di move. Anche usando return std::move(t);
il costruttore di copie viene ancora chiamato.
Posso vedere come questo ha senso, dal momento che t
è const, quindi non dovrebbe legarsi a T&&
. Utilizzare const T&&
nella firma del costruttore di movimento funziona correttamente e ha senso, ma il problema è che poiché other
è const, non è possibile annullare i suoi membri se devono essere annullati, funzionerà solo quando tutti i membri sono scalari o hanno costruttori di movimento con la firma giusta.
Sembra l'unico modo per assicurarsi che il costruttore di movimento sia chiamato nel caso generale per aver fatto t
non-const, ma non mi piace farlo - le cose costanti sono buone e io non si aspetterebbe che il client di T
sapesse che dovevano andare contro quel modulo per aumentare le prestazioni.
Quindi, credo che la mia domanda sia duplice; per prima cosa, un costruttore di mosse deve prendere un riferimento al valore const o non const? E secondo: ho ragione in questa linea di ragionamento? Che dovrei smettere di restituire cose che sono costanti?
Bene, penso che i casi d'uso di restituzione di const temporaries siano piuttosto piccoli. Se lo dichiari in anticipo, allora perché vuoi fare alcune cose con esso prima di tornare. Se no, allora un semplice 'return T()' farebbe comunque. Anche se posso ancora vedere alcuni casi d'uso, penso che siano rari. E, naturalmente, un riferimento di valore da cui non è possibile rubare risorse non ha alcun valore rispetto a un riferimento di lvalue. Domanda interruttiva, comunque. –
A proposito, questo codice non è idoneo per NRVO? Quindi, ciò che "dovrebbe" accadere è che l'oggetto 'const'' t' è costruito nella stessa posizione del valore di ritorno non-const. Quindi, se necessario, il valore di ritorno non const * può * essere spostato dal chiamante tramite il costruttore di movimento non const (o un operatore di assegnazione movimento). Nel caso della costruzione, tuttavia, sarebbe di nuovo idoneo per la copia elision e 't' potrebbe essere costruito direttamente in qualunque cosa venga inizializzata usando una chiamata a' generate_t() '. Cosa sta impedendo a VC11 di realizzare questa ottimizzazione? –
_consting things is good form_ non se si desidera modificarli, ad es. spostandoci da loro. –