0Pricing
C++ Academy · Lezione

std::move e std::forward

Converti gli lvalue in rvalue con std::move e preservi la categoria del valore con std::forward

std::move e std::forward è una lezione C++ Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C++ Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C++ Academy include 4 lezioni in totale.

Due cugini, compiti diversi

std::move e std::forward sono entrambi cast valutati in fase di compilazione. Sembrano simili, ma risolvono problemi diversi.

std::move: cast sempre a rvalue

std::move(x) converte incondizionatamente x in un riferimento rvalue. La funzione che riceve il valore può quindi acquisirne le risorse.

std::string s = "Hello";
std::string t = std::move(s);   // move-constructs t from s
// s is now in a valid-but-unspecified state

Quando usare move

Usi std::move nei seguenti casi:

  • nei costruttori di spostamento e negli operatori di assegnazione tramite spostamento
  • quando restituisce una variabile locale e vuole forzare uno spostamento (è raramente necessario, perché di solito si applica l'RVO)
  • quando passa a una funzione sink una variabile locale di cui non ha più bisogno

Implementazione di std::move

È semplicemente uno static_cast sotto mentite spoglie:

template <typename T>
typename std::remove_reference<T>::type&& move(T&& t) noexcept {
    return static_cast<typename std::remove_reference<T>::type&&>(t);
}

std::forward: preservare la categoria

In un template che usa un forwarding reference (T&&), std::forward<T>(x) riconverte x nella categoria originale, lvalue o rvalue. Si usa per il perfect forwarding.

template <typename T>
void wrapper(T&& arg) {
    target(std::forward<T>(arg));  // forwards as lvalue or rvalue depending on T
}

Perché è necessario il forwarding

All'interno del template, il parametro ha un nome e diventa quindi un lvalue, anche se il chiamante ha passato un rvalue. std::forward recupera la categoria originale.

Senza std::forward

Senza forward, ogni argomento verrebbe passato come lvalue all'interno del wrapper, annullando qualsiasi semantica di spostamento desiderata dal chiamante.

template <typename T>
void wrapper(T&& arg) {
    target(arg);    // always lvalue — wrong
}

Specificare sempre il parametro template di forward

std::forward<T> richiede l'argomento template esplicito. Senza di esso, il comportamento sarebbe errato.

Esempio di perfect forwarding

Una funzione factory che inoltra gli argomenti del costruttore preserva le distinzioni tra rvalue e lvalue, migliorando l'efficienza.

template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

Spostare una sola volta

Ogni oggetto dovrebbe essere utilizzato come sorgente di uno spostamento al massimo una volta. Dopo lo spostamento, si trova in uno stato valido ma non specificato: in genere lo si riassegna o lo si distrugge. Usare un oggetto da cui è stato eseguito uno spostamento senza prima riassegnarlo può causare bug difficili da individuare.

Regole pratiche

Un modello mentale rapido:

  • Ha un tipo concreto e vuole spostarlo → std::move
  • Ha un parametro template e vuole preservarne la categoria → std::forward<T>

Verifica rapida

All'interno di una funzione template con il parametro T&& arg, come inoltra arg preservandone la categoria lvalue/rvalue?

Riepilogo

std::move esegue una conversione incondizionata a rvalue: lo usi sugli oggetti concreti da cui vuole acquisire le risorse. std::forward<T> preserva la categoria del valore all'interno dei template generici: lo usi per il perfect forwarding.

Domande Frequenti

La lezione «std::move e std::forward» è gratuita?

Sì — il testo completo di «std::move e std::forward» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C++ Academy, passa a CoddyKit PRO. Il corso C++ Academy include 4 lezioni in totale.

Cosa imparerò in «std::move e std::forward»?

Converti gli lvalue in rvalue con std::move e preservi la categoria del valore con std::forward Eserciti C++ Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C++ Academy?

Non è richiesta alcuna esperienza precedente. C++ Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «std::move e std::forward»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C++ Academy?

Sì. Ogni lezione C++ Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Lvalue e rvalue: la distinzione
  2. Riferimenti rvalue e sintassi &&
  3. std::move e std::forward
  4. Costruttori di move e assegnazione di move
← Torna a C++ Academy