Herb cevabı (düzenlemeden önceki) aslında bir tür iyi bir örnek verdi olmamalıdır hareket edebilir: std::mutex
.
İşletim sisteminin yerel muteks türü (örneğin pthread_mutex_t
, POSIX platformlarında) "konum değişmezi" olmayabilir, yani nesnenin adresi değerinin bir parçasıdır. Örneğin, işletim sistemi başlatılmış tüm muteks nesnelerine işaret edenlerin bir listesini tutabilir. Eğer std::mutex
(OS onun muteksler işaretçilerin bir listesini tutar çünkü) olduğunda ya sabit kalan gereken bir veri üyesi ve yerli türünün adresi olarak bir doğal OS muteks türü içerdiği std::mutex
o kalacaktı böylece yığın üzerinde yerli muteks türü saklamak zorunda kalacak std::mutex
nesneler arasında hareket ettirildiğinde aynı konum veya std::mutex
hareket etmemelidir. Yığın üzerinde saklamak mümkün değildir, çünkü bir std::mutex
kurucuya sahiptir constexpr
ve sürekli başlatma için uygun olmalıdır (yani statik başlatma), böylece globalstd::mutex
programın yürütülmesi başlamadan önce oluşturulması garanti edilir, bu nedenle kurucusu kullanamaz new
. Yani kalan tek seçenek std::mutex
taşınmaz olmaktır.
Aynı mantık, sabit bir adres gerektiren bir şey içeren diğer türler için de geçerlidir. Kaynağın adresinin sabit kalması gerekiyorsa, hareket ettirmeyin!
Hareket etmemek için başka bir argüman std::mutex
daha var ki bu, bunu güvenli bir şekilde yapmanın çok zor olacağıdır, çünkü hareket edildiği anda hiç kimsenin muteksi kilitlemeye çalışmadığını bilmeniz gerekir. Muteksler, veri yarışlarını önlemek için kullanabileceğiniz yapı taşlarından biri olduğundan, yarışlara karşı güvenli olmasalar talihsiz olurdu! Bir taşınmaz ile, bir std::mutex
kez inşa edildikten ve yok edilmeden önce, herhangi birinin ona yapabileceği tek şeyin onu kilitlemek ve kilidini açmak olduğunu bilirsiniz ve bu işlemlerin iş parçacığı açısından güvenli olduğu ve veri yarışları getirmediği açıkça garanti edilir. Aynı argüman std::atomic<T>
nesneler için de geçerlidir : atomik olarak hareket ettirilmedikçe, onları güvenli bir şekilde taşımak mümkün olmazdı, başka bir iş parçacığı aramaya çalışıyor olabilircompare_exchange_strong
hareket ettiği anda nesnenin üzerinde. Dolayısıyla, türlerin taşınabilir olmaması gereken başka bir durum, güvenli eşzamanlı kodun düşük seviyeli yapı taşları oldukları ve üzerlerindeki tüm işlemlerin atomikliğini sağlamaları gerektiği durumlardır. Nesne değeri herhangi bir zamanda yeni bir nesneye taşınabilirse, her atomik değişkeni korumak için bir atomik değişken kullanmanız gerekir, böylece onu kullanmanın güvenli olup olmadığını veya taşınmış olduğunu bilirsiniz ... ve korumak için bir atomik değişken bu atomik değişken ve benzeri ...
Sanırım bir nesne, bir değerin bir değerinin veya bir değerin soyutlamasının sahibi olarak hareket eden bir tür değil, yalnızca saf bir bellek parçası olduğunda, onu hareket ettirmenin bir anlam ifade etmediğini söyleyeceğim. int
Hareket edememe gibi temel türler : onları taşımak sadece bir kopyadır. Bağırsakları sökemezsiniz int
, değerini kopyalayabilir ve sonra sıfıra ayarlayabilirsiniz, ancak yine int
de bir değeri vardır, sadece bayt bellek. Ama int
hala hareketlidil açısından, çünkü bir kopya geçerli bir taşıma işlemidir. Kopyalanamayan türler için, bellek parçasını hareket ettirmek istemiyorsanız veya hareket ettiremiyorsanız ve değerini de kopyalayamıyorsanız, o zaman taşınabilir değildir. Bir muteks veya bir atomik değişken, belleğin belirli bir yeridir (özel özelliklerle işlenir), bu nedenle taşınması mantıklı değildir ve aynı zamanda kopyalanamaz, bu nedenle taşınamaz.