std::move în C++

Mută elementele unui interval la o destinație, fără să le copieze (versiunea din <algorithm>).

Sintaxă
OutputIt move(InputIt first, InputIt last, OutputIt d_first);

Ce face std::move

Varianta cu trei argumente a lui std::move, din <algorithm>, funcționează ca std::copy, dar mută fiecare element. Pentru tipuri precum std::string sau std::vector, mutarea preia memoria în loc să o copieze, deci este mult mai rapidă.

După mutare, elementele din sursă există încă, dar sunt într-o stare validă și nespecificată (de obicei goale). Nu te baza pe valoarea lor. Nu confunda cu std::move(x) cu un singur argument, din <utility>, care doar transformă x într-o valoare ce poate fi mutată.

Parametri

Parametru Descriere
first, last Elementele sursă.
d_first Începutul destinației.

Ce returnează

Iterator după ultimul element scris.

Exemple

Exemplul 1: Mutarea unor texte în alt vector

Pe libc++, textele din sursă rămân goale după mutare; standardul garantează doar că sunt valide.

#include <algorithm>
#include <iterator>
#include <print>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> ciorne{"Raport lunar complet pentru martie", "Ofertă pentru clientul din Brașov"};
    std::vector<std::string> trimise;

    std::move(ciorne.begin(), ciorne.end(), std::back_inserter(trimise));

    std::println("Trimise: {}", trimise.size());
    std::println("Primul trimis: {}", trimise[0]);
    std::println("Ciornele au acum {} elemente", ciorne.size());
    std::println("Prima ciornă este goală: {}", ciorne[0].empty());
}

Rezultat

Trimise: 2
Primul trimis: Raport lunar complet pentru martie
Ciornele au acum 2 elemente
Prima ciornă este goală: true

Exemplul 2: Unique_ptr se pot doar muta

std::copy nu ar compila aici, pentru că std::unique_ptr nu se poate copia.

#include <algorithm>
#include <memory>
#include <print>
#include <vector>

int main() {
    std::vector<std::unique_ptr<int>> sursa;
    sursa.push_back(std::make_unique<int>(7));
    sursa.push_back(std::make_unique<int>(13));

    std::vector<std::unique_ptr<int>> dest(2);
    std::move(sursa.begin(), sursa.end(), dest.begin());

    std::println("dest: {} {}", *dest[0], *dest[1]);
    std::println("sursa[0] este gol: {}", sursa[0] == nullptr);
}

Rezultat

dest: 7 13
sursa[0] este gol: true

Greșeli frecvente

  • Folosești elementele din sursă după mutare ca și cum ar avea valoarea veche.
  • Uiți #include <algorithm> și compilatorul alege alt std::move sau dă erori greu de înțeles.

Comenzi înrudite

  • std::copy: Copiază elementele unui interval (copy) sau primele n elemente (copy_n) la o destinație.
  • std::swap_ranges: Schimbă între ele elementele a două intervale de aceeași lungime, poziție cu poziție.