Domanda

Una delle nuove fantastiche funzionalità del prossimo standard C ++, C ++ 0x, sono " riferimenti di valore. " Un riferimento al valore è simile a un riferimento al valore (normale), tranne per il fatto che può essere associato a un valore temporaneo (normalmente, un temporaneo può essere associato solo a un const riferimento):

void FunctionWithLValueRef(int& a) {...}
void FunctionWithRValueRef(int&& a) {...}

int main() {
     FunctionWithLValueRef(5); // error, 5 is a temporary
     FunctionWithRValueRef(5); // okay
}

Quindi, perché hanno inventato un tipo completamente nuovo, anziché semplicemente rimuovere le restrizioni sui normali riferimenti per consentire loro di essere vincolati ai provvisori?

È stato utile?

Soluzione

Sarebbe inutile. Cambieresti la cosa nella funzione e la modifica andrebbe persa immediatamente perché la cosa era in realtà temporanea.

Il motivo del nuovo tipo deriva dalla necessità di essere in grado di decidere cosa sia effettivamente un valore e cosa no. Solo così puoi effettivamente usarli per le cose interessanti che vengono utilizzate.

string toupper(string && s) { // for nonconst rvalues
    for(char &c : s) make_uppercase(c);
    return move(s); // move s into a returned string object
}

string toupper(string const& s) { // for the rest
    // calls the rvalue reference version, by passing 
    // an rvalue copy.
    return toupper(string(s));
}

Ora, se hai del valore e lo passi al toupper, il valore può essere modificato direttamente, perché sappiamo che il temporaneo è comunque una cosa da buttare via, quindi possiamo anche cambiarlo e non è necessario copiarlo esso. Inoltre, la stessa osservazione viene utilizzata per la cosa chiamata costruttori di mosse e assegnazione di mosse. Il lato destro non viene copiato, ma le sue cose vengono semplicemente rubate e spostate in *this.

Se dovessi dire che i valori possono legarsi a riferimenti a valori non costanti, non avresti modo di capire se alla fine fa riferimento a un valore (oggetto denominato) o un valore (temporaneo).


Probabilmente è poco più noto, ma comunque utile, puoi mettere i riqualificatori di valore lvalue o rvalue su una funzione membro. Ecco un esempio, che estende naturalmente la semantica esistente dei riferimenti rvalue al parametro oggetto implicito:

struct string {
    string& operator=(string const& other) & { /* ... */ }
};

Ora, non puoi più dire

string() = "hello";

Il che è confuso e non ha davvero senso per la maggior parte del tempo. Ciò che & sopra fa è che l'operatore di assegnazione può essere invocato solo su valori. Lo stesso può essere fatto per i valori, inserendo &&.

Altri suggerimenti

Perché l'aggiunta di un nuovo tipo di riferimento consente di scrivere due overload di un metodo:

void CopyFrom(MyClass &&c)
{
    dataMember.swap(c);
}

void CopyFrom(const MyClass &c)
{
    dataMember.copyTheHardWay(c);
}

La versione che accetta il nuovo tipo di riferimento è autorizzata a modificare la variabile che riceve, poiché quella variabile non verrà utilizzata da nessun'altra parte. Quindi può & Quot; rubare & Quot; il suo contenuto.

Questo è il motivo per cui questa funzione è stata aggiunta; il mantenimento di un tipo di riferimento non raggiungerebbe l'obiettivo desiderato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top