C++ Academy · Oppitunti

std::move ja std::forward

Muunna lvaluet rvalueiksi std::movella ja säilytä arvokategoria std::forwardilla.

Oppitunti 3/413 vaihetta

std::move ja std::forward on ilmainen C++ Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu C++ Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C++ Academy-kurssilla on yhteensä 4 oppituntia.

Kaksi sukulaista, eri tehtävät

std::move ja std::forward ovat molemmat käännösaikaisia tyyppimuunnoksia. Ne näyttävät samanlaisilta, mutta ratkaisevat eri ongelmia.

std::move: muunna aina rvalue-arvoksi

std::move(x) muuntaa x:n ehdoitta rvalue-viittaukseksi. Vastaanottava funktio voi tällöin varastaa sen resurssit.

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

Milloin move-funktiota käytetään

Käyttäkää std::move-funktiota seuraavissa tilanteissa:

  • siirtorakentajissa ja siirtosijoitusoperaattoreissa
  • palautettaessa paikallinen muuttuja, kun siirto halutaan pakottaa (harvoin tarpeen — RVO yleensä toteutuu)
  • välitettäessä paikallinen muuttuja, jota ei enää tarvita, sink-funktiolle

std::move-funktion toteutus

Se on vain naamioitu static_cast:

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: säilytä arvokategoria

Forwarding reference -viittausta (T&&) käyttävässä mallissa std::forward<T>(x) muuntaa x:n takaisin alkuperäiseen arvokategoriaansa (lvalue- tai rvalue-arvoksi). Tätä käytetään täydelliseen välitykseen.

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

Miksi välitystä tarvitaan

Mallin sisällä parametrilla on nimi — joten se on lvalue, vaikka kutsuja välitti rvalue-arvon. std::forward palauttaa alkuperäisen arvokategorian.

Ilman std::forward-funktiota

Ilman forward-funktiota jokainen argumentti välitettäisiin kääreen sisällä lvalue-arvona, mikä estäisi kutsujan haluaman siirtosemantiikan.

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

Määritä forward-funktion malliparametri aina

std::forward<T> vaatii eksplisiittisen malliparametrin. Ilman sitä toiminta olisi virheellistä.

Esimerkki täydellisestä välityksestä

Rakentajan argumentit välittävä tehdasfunktio säilyttää lvalue- ja rvalue-arvojen erot tehokkuuden vuoksi.

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

Siirtäkää kerran

Kustakin oliosta tulisi siirtää resurssit enintään kerran. Siirron jälkeen olio on kelvollisessa mutta määrittelemättömässä tilassa — yleensä se määritetään uudelleen tai tuhotaan. Siirretyn olion käyttäminen ilman sitä edeltävää uudelleenmäärittämistä voi aiheuttaa vaikeasti havaittavia virheitä.

Nyrkkisäännöt

Nopea ajatusmalli:

  • Teillä on konkreettinen tyyppi ja haluatte siirtää sen → std::move
  • Teillä on malliparametri ja haluatte säilyttää arvokategorian → std::forward<T>

Pikatarkistus

Miten välitätte arg-parametrin mallifunktion sisällä, kun parametrina on T&& arg, ja säilytätte samalla sen lvalue- tai rvalue-arvokategorian?

Kertaus

std::move muuntaa ehdoitta rvalue-arvoksi — käyttäkää sitä konkreettisiin olioihin, joiden resurssit haluatte varastaa. std::forward<T> säilyttää arvokategorian yleisissä malleissa — käyttäkää sitä täydelliseen välitykseen.

Aloita maksutta

Opi C++ tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
51
Oppitunnit
203

Usein kysytyt kysymykset

Onko oppitunti ”std::move ja std::forward” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa C++ Academy-oppimispolun 3 oppituntia, myös oppitunnin “std::move ja std::forward”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. C++ Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”std::move ja std::forward”?

Muunna lvaluet rvalueiksi std::movella ja säilytä arvokategoria std::forwardilla. Harjoittelet C++ Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C++ Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C++ Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”std::move ja std::forward”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C++ Academy-oppitunnilla?

Kyllä. Jokainen C++ Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Lvalue ja rvalue: ero
  2. Rvalue-viitteet ja &&-syntaksi
  3. std::move ja std::forward
  4. Siirtokonstruktorit ja siirtosijoitus
← Takaisin: C++ Academy