Fungsi C ++ 11 std::move(x)
tidak benar-benar memindahkan apa pun. Itu hanya sebuah pemeran untuk nilai-r. Mengapa ini dilakukan? Bukankah ini menyesatkan?
c++
c++11
move-semantics
rvalue-reference
c++-faq
Howard Hinnant
sumber
sumber
std::move
benar - benar bergerak ..std::char_traits::move
std::remove()
yang tidak menghapus elemen: Anda masih harus meneleponerase()
untuk benar-benar menghapus elemen-elemen itu dari wadah. Jadimove
tidak bergerak,remove
tidak menghapus. Saya akan memilih namamark_movable()
untukmove
.mark_movable()
membingungkan juga. Ini menunjukkan ada efek samping yang abadi di mana sebenarnya tidak ada.Jawaban:
Benar bahwa
std::move(x)
itu hanya gips untuk menilai ulang - lebih khusus untuk xvalue , yang bertentangan dengan prvalue . Dan memang benar bahwa memiliki pemain bernamamove
kadang-kadang membingungkan orang. Namun maksud penamaan ini bukan untuk membingungkan, melainkan untuk membuat kode Anda lebih mudah dibaca.Sejarah
move
tanggal kembali ke proposal pindah asli pada tahun 2002 . Makalah ini pertama kali memperkenalkan referensi nilai, dan kemudian menunjukkan cara menulis yang lebih efisienstd::swap
:Kita harus ingat bahwa pada titik ini dalam sejarah, satu - satunya hal yang
&&
mungkin bisa berarti adalah logis dan . Tidak ada yang akrab dengan referensi nilai, atau implikasi dari melemparkan nilai ke nilai (sementara tidak membuat salinan seperti yangstatic_cast<T>(t)
akan dilakukan). Jadi pembaca kode ini secara alami akan berpikir:Perhatikan juga bahwa
swap
ini hanyalah stand-in untuk semua jenis algoritma permutasi-modifikasi. Diskusi ini jauh , jauh lebih besar daripadaswap
.Kemudian proposal tersebut memperkenalkan sintaksis gula yang menggantikannya
static_cast<T&&>
dengan sesuatu yang lebih mudah dibaca yang menyampaikan tidak tepat apa , melainkan mengapa :Yaitu
move
hanya untuk sintaksisstatic_cast<T&&>
, dan sekarang kodenya cukup sugestif mengenai mengapa para pemain itu ada di sana: untuk memungkinkan pemindahan semantik!Orang harus memahami bahwa dalam konteks sejarah, hanya sedikit orang pada saat ini yang benar-benar memahami hubungan intim antara nilai-nilai dan memindahkan semantik (walaupun makalah ini mencoba menjelaskannya juga):
Jika pada saat
swap
itu disajikan seperti ini:Maka orang akan melihat itu dan berkata:
Poin utama:
Seperti itu, menggunakan
move
, tidak ada yang pernah bertanya:Seiring berlalunya waktu dan proposal itu disempurnakan, gagasan nilai dan nilai diubah menjadi kategori nilai yang kita miliki saat ini:
(gambar tanpa malu-malu dicuri dari dirkgently )
Dan hari ini, jika kita ingin
swap
mengatakan apa yang dilakukannya, daripada mengapa , itu akan terlihat seperti:Dan pertanyaan yang harus ditanyakan oleh setiap orang kepada diri mereka sendiri adalah apakah kode di atas lebih atau kurang dapat dibaca daripada:
Atau bahkan yang asli:
Dalam hal apa pun, pembuat program C ++ pekerja harian harus tahu bahwa di balik tudung
move
, tidak ada yang lebih dari sekadar pemeran. Dan programmer C ++ pemula, setidaknya denganmove
, akan diberitahu bahwa tujuannya adalah untuk pindah dari rhs, sebagai lawan menyalin dari rhs, bahkan jika mereka tidak mengerti persis bagaimana hal itu dilakukan.Selain itu, jika seorang programmer menginginkan fungsi ini dengan nama lain,
std::move
tidak memiliki monopoli pada fungsi ini, dan tidak ada keajaiban bahasa non-portabel yang terlibat dalam implementasinya. Sebagai contoh jika seseorang ingin kodeset_value_category_to_xvalue
, dan menggunakannya sebagai gantinya, itu sepele untuk melakukannya:Dalam C ++ 14 itu menjadi lebih ringkas:
Jadi, jika Anda cenderung, hiasi
static_cast<T&&>
apa pun yang menurut Anda terbaik, dan mungkin akhirnya Anda akan mengembangkan praktik terbaik baru (C ++ terus berkembang).Jadi apa yang
move
dilakukan dalam hal kode objek yang dihasilkan?Pertimbangkan ini
test
:Dikompilasi dengan
clang++ -std=c++14 test.cpp -O3 -S
, ini menghasilkan kode objek ini:Sekarang jika tes diubah menjadi:
Sama sekali tidak ada perubahan sama sekali dalam kode objek. Seseorang dapat menggeneralisasi hasil ini ke: Untuk objek yang bergerak sepele ,
std::move
tidak memiliki dampak.Sekarang mari kita lihat contoh ini:
Ini menghasilkan:
Jika Anda menjalankan
__ZN1XaSERKS_
melaluic++filt
menghasilkan:X::operator=(X const&)
. Tidak mengherankan di sini. Sekarang jika tes diubah menjadi:Kemudian masih tidak ada perubahan apa pun dalam kode objek yang dihasilkan.
std::move
tidak melakukan apa pun selain melemparkanj
ke nilai sebuah, dan kemudian nilai ituX
mengikat ke operator penugasan salinanX
.Sekarang mari tambahkan operator pemindahan tugas ke
X
:Sekarang kode objek tidak berubah:
Menjalankan
__ZN1XaSEOS_
melaluic++filt
mengungkapkan bahwaX::operator=(X&&)
yang dipanggil bukannyaX::operator=(X const&)
.Dan hanya itu yang ada untuk
std::move
! Ini benar-benar menghilang pada saat dijalankan. Satu-satunya dampaknya adalah pada saat kompilasi di mana ia dapat mengubah apa yang disebut overload.sumber
digraph D { glvalue -> { lvalue; xvalue } rvalue -> { xvalue; prvalue } expression -> { glvalue; rvalue } }
untuk kepentingan umum :) Unduh di sini sebagai SVGallow_move
;)movable
.std::move
kervalue_cast
: youtube.com/…rvalue_cast
apakah ambigu dalam maknanya: jenis nilai apa yang dikembalikan?xvalue_cast
akan menjadi nama yang konsisten di sini. Sayangnya, kebanyakan orang, saat ini, juga tidak mengerti apa yang dilakukannya. Dalam beberapa tahun lagi, pernyataan saya semoga menjadi salah.Biarkan saya tinggalkan kutipan di sini dari C ++ 11 FAQ yang ditulis oleh B. Stroustrup, yang merupakan jawaban langsung untuk pertanyaan OP:
Omong-omong, saya sangat menikmati FAQ - layak dibaca
sumber