Sobes.tech
Middle

Co się dzieje podczas przenoszenia obiektu typu std::string w C++?

sobes.tech AI

Odpowiedź od AI

Przenosząc std::string, własność zasobu (pamięci) jest przekazywana z obiektu źródłowego do docelowego. Zamiast kopiować zawartość łańcucha (znaki), kopiowany jest tylko wskaźnik do bufora, jego rozmiar i pojemność. Obiekt źródłowy znajduje się wtedy w stanie ważnym, ale nieokreślonym (zwykle wskaźnik staje się nullem, a rozmiar i pojemność są zerowane), co zapobiega podwójnemu zwolnieniu pamięci. Jest to znacznie szybsze niż pełne kopiowanie, szczególnie dla długich łańcuchów.

#include <string>
#include <iostream>
#include <utility>

int main() {
    std::string original = "Bardzo długi łańcuch, którego nie chcesz kopiować";
    std::cout << "Oryginał (przed przeniesieniem): " << original << std::endl;

    // Przenosimy original do moved
    std::string moved = std::move(original);

    std::cout << "Przeniesione (po przeniesieniu): " << moved << std::endl;
    // original jest teraz w stanie ważnym, ale nieokreślonym.
    // Próba użycia original po przeniesieniu bez inicjalizacji jest nieokreślonym zachowaniem.
    // Jednak wiele implementacji resetuje go do stanu pustego.
    // std::cout << "Oryginał (po przeniesieniu): " << original << std::endl; // Niebezpieczne!

    return 0;
}

Konstruktor przenoszący lub operator przypisania:

  • Przypisuje wskaźnik do bufora do obiektu docelowego.
  • Przypisuje rozmiar i pojemność do obiektu docelowego.
  • Ustawia wskaźnik na buforze obiektu źródłowego na nullptr.
  • Ustawia rozmiar i pojemność obiektu źródłowego na 0.

Jest to realizowane dzięki semantyce przenoszenia (referencje rvalue i specjalne konstruktory/operatorzy).