Hareket etmek nesneyi kullanılabilir bir durumda mı bırakır?

İki vektör aldığımı varsayalım ve birini diğerine taşıyorum, v1 = std :: move (v2) ; v2 bundan sonra hala kullanılabilir durumda olacak mı?

14
Bu, bir stackoverflow.com/q/7027523/576911 kopyası gibi görünüyor. Bu cevaba bakınız: stackoverflow.com/questions/7027523/… nesnesinden bir nesne taşındı.
katma yazar Howard Hinnant, kaynak

3 cevap

N3290'dan, 17.6.5.15 Kütüphane türlerinin taşındığı durum [lib.types.movedfrom]

      
  1. C ++ standart kitaplığında tanımlanan türlerin nesneleri (12.8) 'den hareket ettirilebilir. Taşıma işlemleri açıkça belirtilebilir veya örtük olarak oluşturulabilir. Aksi belirtilmedikçe, bu tür taşınan nesneler geçerli ancak belirtilmemiş bir duruma yerleştirilecektir.
  2.   

Durum geçerli olduğundan, v2 üzerinde güvenli bir şekilde çalışabileceğiniz anlamına gelir (ör., Ona atayarak, bilinen bir duruma geri yükler). Bununla birlikte, belirtilmemiş olduğundan, bu durumda olduğu sürece v2.empty() için herhangi bir belirli değere güvenemeyeceğiniz anlamına gelir (ancak çağırmak, programın çökmesine neden olmaz).

Taşıyıcı anlambiliminin bu aksiyomunun ("Nesnelerden taşınan, geçerli fakat belirtilmemiş bir durumda bırakılır"), tüm kodun (çoğu zaman), yalnızca Standart Kitaplık bileşenlerini değil, doğru çalışması gereken bir şey olduğunu unutmayın. Kopya yapıcıların semantiği gibi olmalıdır bir kopyasını oluşturmalı, ancak zorunlu değildir.

22
katma
+1, ancak yazıldığı şekilde, v2 = std :: vector {}; 'dan sonra v2 ' nin boş olup olmadığını bilmiyorsunuz gibi görünüyor.
katma yazar Gabriel, kaynak
@Gabriel İyi nokta, bir düzenleme sırayla.
katma yazar Luc Danton, kaynak
Zorunlu geçerli olmalı. Aksi halde, nesne kapsam dışına çıktığında ne olur. Büyük ihtimalle veri mağazasında hiçbir şey olmayacak, ama her ne ise geçerli olacak.
katma yazar Damon, kaynak
Belirtilmemiş ancak geçerli durumunda bırakılır. Yani, nesneyi, yalnızca nesnenin geçerli olduğu önkoşul olan şekillerde kullanabilirsiniz. Örneğin, bilinen bir duruma getirmek için vektörde taşınan vektör üzerinde vektör :: clear() öğesini çağırabilir ve ardından nesnelerin içine yerleştirmeye başlayabilirsiniz.
katma yazar bames53, kaynak
Birden fazla (soyut) geçerlilik seviyesi vardır. Dil söz konusu olduğunda, hareket edildikten sonra nesne hala var olduğu sürece geçerlidir, onun yıkıcısı tanımlanamayan davranışlara neden olmadan çağrılabilir. Ancak, nesnenin sözleşmesi, taşınan taşınmaz nedeniyle değiştirilebilir. . Örneğin, bir vektörün sıfır büyüklüğüne (kapasite taşımayan) sahip olması, geçerli bir C ++ vektörüdür, ancak (artık geçersiz kılınan) varsayımı doğrulanmadan, vektör üzerinde belirli bir elemanı belirleyen bir yönteme sahip olan bir nesnedir. Vektör belirli bir boyuta sahip olmalı, ...
katma yazar rwong, kaynak
... izin verilmeyen bir işlem haline gelir (UB'ye neden olur). Bu detaylar nesnenin uygulayıcısı tarafından belgelenmelidir. Uygulayıcı, gerek duyulduğunda, nesnenin kullanılabilirliğini geri yüklemek için belgelenmiş bir yol sağlamalıdır.
katma yazar rwong, kaynak

Hareket ettikten sonra istediğin 'i kullanırsan, şöyle bir şey yapmak istersiniz:

v1 = std::move(v2);
v2.clear();

Bu noktada v1, v2'nin orijinal içeriğine sahip olacak ve v2 iyi tanımlanmış bir boş durumda olacaktır. Bu, tüm STL kapsayıcılarında (ve bu konuyla ilgili dizeler) çalışır ve hareket anlambilimini destekleyen kendi sınıflarınızı uyguluyorsanız, muhtemelen benzer bir şey yapmak isteyeceksiniz.

Eğer STL'nin gerçek uygulaması gerçekte nesneyi boş bir durumda bırakıyorsa, o zaman ikinci clear() aslında bir no-op olacaktır. Aslında, bu durumda, bir derleyicinin, taşıma işleminden sonra temizlemeyi() ortadan kaldırması yasal bir optimizasyon olacaktır.

0
katma