Di Chapter Ownership dan Pemilihan Smart Pointer kita sudah dua kali menulis std::move(...) — sekarang saatnya membuka mekanismenya. Move semantics adalah cara C++ memindahkan resource dari satu variabel ke variabel lain tanpa menyalin isinya: alamat heap tidak diganti, data tidak digandakan; yang berpindah hanyalah kepemilikan, dan sumbernya ditinggalkan dalam keadaan kosong yang sah. Untuk std::unique_ptr yang kekuatannya justru pada larangan menyalin, move adalah satu-satunya pintu perpindahan. Chapter ini memakai unique_ptr untuk menunjukkan tiga arah perpindahan — antar variabel, keluar fungsi, dan masuk container — sebelum detail penuhnya dibedah pada Section Move Semantics dan Value Categories.
std::move: Tanda “Silakan Pindahkan” #
std::move sendiri tidak memindahkan apa pun; ia menandai sebuah ekspresi sebagai “boleh dipindah” sehingga compiler memilih operasi pemindahan alih-alih penyalinan. Saat penanda ini bertemu unique_ptr, hasilnya sederhana dan terukur: alamat yang disimpan sumber dipindahkan ke tujuan, dan sumber menjadi nullptr. Inilah pola yang membuat kepemilikan bisa berpindah tanpa membuka celah dua pemilik — perpindahan dan pengosongan terjadi sebagai satu kesatuan atomik.
#include <iostream>
#include <memory>
#include <utility>
#include <vector>
std::unique_ptr<int> buatNilai(int v) {
return std::make_unique<int>(v); // berpindah keluar tanpa disalin
}
int main() {
auto a = std::make_unique<int>(10);
std::unique_ptr<int> b = std::move(a); // kepemilikan pindah: a -> b
std::cout << "b berisi : " << *b << "\n";
std::cout << "a kosong? " << (a == nullptr ? "ya" : "tidak") << "\n";
auto c = buatNilai(99); // berpindah keluar dari fungsi
std::cout << "c berisi : " << *c << "\n";
std::vector<std::unique_ptr<int>> gudang;
gudang.push_back(std::move(b)); // berpindah masuk ke vector
gudang.push_back(std::move(c));
std::cout << "gudang : " << *gudang[0] << " dan " << *gudang[1] << "\n";
return 0;
}Output yang Dihasilkan:
b berisi : 10
a kosong? ya
c berisi : 99
gudang : 10 dan 99Tiga arah perpindahan terbaca dari program di atas:
- Baris 12 (
std::move(a)): kepemilikan pindah antar variabel —bkini memegang alamat heap berisi 10, danaterbukti kosong pada outputa kosong? ya. - Baris 7 (
return std::make_unique<int>(v);): kepemilikan berpindah keluar dari fungsi secara alami; memanggilbuatNilai(99)menghasilkancyang sah tanpa ekspresimoveeksplisit di pemanggil. - Baris 21-22 (
push_back(std::move(...))):vector<unique_ptr<int>>hampir mustahil dibangun tanpa move — penyalinan dilarang, sehingga setiap elemen harus dipindahkan masuk. - Baris 23 (
*gudang[0]): setelah pindah, objek tetap satu-satunya objek yang sama — tidak ada penggandaan data di sepanjang perjalanannya.
Mengapa Move Layak Ada #
Motif besarnya adalah menghindari penyalinan yang mahal. std::string dengan isi satu paragraf, std::vector dengan jutaan elemen, atau buffer gambar — menyalinnya berarti memesan memori baru dan menggandakan byte demi byte, sedangkan memindahkannya hanya memindahkan tiga penunjuk internal. Dengan move semantics, container seperti std::vector bisa tumbuh tanpa menggandakan setiap elemen, std::string bisa dikembalikan dari fungsi tanpa salinan, dan unique_ptr bisa disimpan di mana saja. Semua itu tanpa biaya tambahan — resource yang sama, hanya berpindah pemilik.
Ada satu keadaan yang wajib dipahami sejak sekarang: moved-from state. Variabel yang sudah dipindahkan sah dan aman diakses — a == nullptr di atas adalah perbandingan yang sah — tetapi isinya tidak lagi menjanjikan apa pun kecuali nilai default tipe itu. Aturan praktisnya: jangan membaca nilai dari variabel yang sudah dipindahkan; nol-kan pemahaman kita bahwa ia kosong, lalu biarkan ia berakhir atau isi ulang.
Move yang kita gunakan di sini baru permukaannya — versi lengkapnya melibatkan rvalue reference, move constructor, dan move assignment yang dibedah tuntas pada Section Move Semantics dan Value Categories. Untuk kebutuhan manajemen memori, yang kita miliki sudah cukup: kepemilikan bisa berpindah, aman, dan eksplisit. Pertanyaan terakhir yang tersisa: apa yang terjadi pada resource itu bila exception menyela di tengah jalan? Itulah topik chapter berikutnya.
Referensi: cppreference — std::move , cppreference — std::unique_ptr .