Jawaban Herb (sebelum diedit) benar-benar memberi contoh yang baik dari jenis yang seharusnya tidak menjadi bergerak: std::mutex.
Jenis mutex asli OS (misalnya pthread_mutex_tpada platform POSIX) mungkin bukan "invarian lokasi" yang berarti alamat objek adalah bagian dari nilainya. Misalnya, OS mungkin menyimpan daftar pointer ke semua objek mutex yang diinisialisasi. Jika std::mutexberisi jenis mutex OS asli sebagai anggota data dan alamat jenis asli harus tetap diperbaiki (karena OS menyimpan daftar penunjuk ke mutexnya) maka salah satu dari std::mutexmereka harus menyimpan jenis mutex asli di heap sehingga akan tetap di lokasi yang sama ketika dipindahkan antar std::mutexobjek atau std::mutextidak boleh bergerak. Menyimpannya di heap tidak mungkin, karena a std::mutexmemiliki constexprkonstruktor dan harus memenuhi syarat untuk inisialisasi konstan (yaitu inisialisasi statis) sehinggastd::mutexdijamin akan dibangun sebelum eksekusi program dimulai, sehingga konstruktornya tidak dapat menggunakannya new. Jadi satu-satunya pilihan yang tersisa adalah std::mutexmenjadi tidak tergoyahkan.
Alasan yang sama berlaku untuk jenis lain yang berisi sesuatu yang membutuhkan alamat tetap. Jika alamat sumber daya harus tetap, jangan pindahkan!
Ada argumen lain untuk tidak bergerak, std::mutexyaitu akan sangat sulit melakukannya dengan aman, karena Anda perlu tahu bahwa tidak ada yang mencoba mengunci mutex pada saat mutex sedang dipindahkan. Karena mutex adalah salah satu blok bangunan yang dapat Anda gunakan untuk mencegah balapan data, akan sangat disayangkan jika mereka tidak aman terhadap balapan itu sendiri! Dengan immovable, std::mutexAnda tahu satu-satunya hal yang dapat dilakukan siapa pun padanya setelah dibuat dan sebelum dihancurkan adalah dengan menguncinya dan membukanya, dan operasi tersebut secara eksplisit dijamin aman untuk thread dan tidak memperkenalkan data race. Argumen yang sama ini berlaku untuk std::atomic<T>objek: kecuali mereka dapat dipindahkan secara atomis, tidak mungkin untuk memindahkannya dengan aman, utas lain mungkin mencoba memanggilcompare_exchange_strongpada objek tepat pada saat itu sedang dipindahkan. Jadi kasus lain di mana jenis tidak boleh dipindahkan adalah di mana mereka adalah blok bangunan tingkat rendah dari kode bersamaan yang aman dan harus memastikan atomisitas dari semua operasi pada mereka. Jika nilai objek dapat dipindahkan ke objek baru kapan saja, Anda perlu menggunakan variabel atom untuk melindungi setiap variabel atom sehingga Anda tahu apakah aman untuk menggunakannya atau telah dipindahkan ... dan variabel atom untuk melindungi variabel atom itu, dan seterusnya ...
Saya pikir saya akan menggeneralisasi untuk mengatakan bahwa ketika sebuah objek hanyalah sepotong memori murni, bukan jenis yang bertindak sebagai pemegang nilai atau abstraksi nilai, tidak masuk akal untuk memindahkannya. Tipe mendasar seperti inttidak bisa bergerak: memindahkannya hanyalah salinan. Anda tidak dapat merobek nyali dari sebuah int, Anda dapat menyalin nilainya dan kemudian mengaturnya ke nol, tetapi itu masih intdengan nilai, itu hanya byte memori. Tapi intmasih bisa dipindahkandalam istilah bahasa karena salinan adalah operasi pemindahan yang valid. Namun untuk jenis yang tidak dapat disalin, jika Anda tidak ingin atau tidak dapat memindahkan bagian memori dan Anda juga tidak dapat menyalin nilainya, maka itu tidak dapat dipindahkan. Mutex atau variabel atom adalah lokasi memori tertentu (diperlakukan dengan properti khusus) sehingga tidak masuk akal untuk dipindahkan, dan juga tidak dapat disalin, jadi tidak dapat dipindahkan.