2013-07-11 20 views
12

Bu kod beni karıştırır:std :: map içindeki anahtar/değer türleri için gereksinimleri kopyala/taşı

struct foo { 
    int i; 

    foo(int j) : i(j) {} 

    foo(const foo &) = delete; 
    foo(foo &&) = delete; 
    foo &operator=(const foo&) = delete; 
    foo &operator=(foo&&) = delete; 
}; 

bool operator<(const foo &f1, const foo &f2) 
{ 
    return f1.i < f2.i; 
} 

int main(int argc, char **argv) 
{ 
    std::map<foo,int> f; 
    std::map<foo,int> f2 = f; //error (as expected) 
    std::map<foo,int> f3 = std::move(f); //no error (why?) 
    return 0; 
} 

Orada hiçbir hata alıyorum olduğundan, (hatta bunun içine başka önemli nesnesinin taşınmasının) hiçbir anahtar nesne oluşturulan bir harita taşırken gibi görünüyor.

Neden değil? Bu davranışa C++ 11 standardına göre güvenebilir miyim?

Daha genel olarak, anahtarında std::map anahtar ve değer türleri üzerinde hangi koşullar altında kopyalanıyor?

+0

atanır. –

+1

@MooingDuck, allocator türünün –

+0

ah doğru yaymadığı durumlarda doğru değil, ayırıcılar her şeye karışabilirler. –

cevap

14

Bir haritanın bir kopyaya kopyalanması, her bir öğenin kopyalanmasını gerektirir. Öğeleri kopyalayamadığınız için haritaları kopyalayamazsınız. Bu tip nesnelerin tarafından tamamen belirlenen statik hususlar, sadece, çünkü gerçek harita nesne zamanında boş olup olmadığı

, önemsizdir. Konteyner düğüm tabanlı ve hiçbir gerçek olduğu için

(O sin(0) sonuç bir tam sayıdır açıkça kayan nokta birimi gerektirir neden sormak gibi bir şey.)

diğer taraftan, tüm haritayı Hareketli, gayet değerler mutasyona uğradı, sadece düğümler. Aslında, düğüm tabanlı kapların hareket ettirilmesi veya taşınması, öğelerin kopyalanabilir veya taşınır veya atanabilir olmasını gerektirmez.

(Bu, std::allocator<value_type> gibi uygun bir şekilde dinamik belleği yöneten tüm kaplar için geçerli olmalıdır, ancak std::array gibi bir şey için elbette doğru olmaz ve bekleyip tutamayacağı ilginç olurdu) tahsis şeması düğümleri toptan taşımak mümkün.) değilse sadece map taşındı çünkü std::dynarray için, @Jonathan Wakely kaydetti ve gibi

+4

"M" türünde bir eşlemin atanması, öğe türlerinin 'M' içine 'MoveInsertable' için' M' şeklinde olmasını gerektirir: allocator_traits :: propagate_on_container_move_assignment :: value' false –

+0

@JonathanWakely: Oh dear. Evet, bu çok güzel bir nokta. Her şey tamamlayıcıya bağlı! –

+3

Lanet olası lanet tümörleri: - \ –

3

map değil elemanları, hata yok. Sadece öğelere işaretçiler, anahtar ve değer üzerinde bir _o_ gereksinimlerini taşıyan

İlgili konular