2013-07-11 34 views
12

Mã này confuses me:Yêu cầu sao chép/di chuyển đối với các loại khóa/giá trị trong std :: map?

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; 
} 

Bởi vì tôi nhận được không có lỗi đó, nó có vẻ như khi di chuyển bản đồ không có đối tượng chủ chốt được tạo ra (thậm chí không cho di chuyển một đối tượng quan trọng vào nó).

Tại sao không? Tôi có thể dựa vào hành vi này theo tiêu chuẩn C++ 11 không?

Nói chung, yêu cầu sao chép/di chuyển nào có vị trí std::map trên các loại khóa và giá trị và trong điều kiện nào?

+0

di chuyển các yêu cầu _no_ của các vị trí trên bản đồ trên khóa và giá trị. –

+1

@MooingDuck, điều đó không đúng nếu loại cấp phát không lan truyền –

+0

ah đúng, người phân bổ có thể gây rối với mọi thứ. –

Trả lời

14

Việc gán bản sao của một bản đồ này sang bản đồ khác yêu cầu sao chép từng mục. Vì bạn không thể sao chép các mục, bạn không thể sao chép gán các bản đồ.

Cho dù đối tượng bản đồ thực tế là có sản phẩm nào trong thời gian chạy là không quan trọng, vì đây là những thuần túy tĩnh cân nhắc, xác định hoàn toàn bởi các loại của các đối tượng.

(Nó giống như hỏi tại sao sin(0) đòi hỏi một floating point unit khi rõ ràng kết quả là một số nguyên.)

Di chuyển toàn bộ bản đồ, mặt khác, là tốt vì các container là nút dựa trên và không thực tế các giá trị bị biến đổi, chỉ các nút là. Trên thực tế, các vùng chứa dựa trên nút di chuyển-xây dựng hoặc chuyển nhượng dựa trên nút không yêu cầu các phần tử có thể sao chép được hoặc có thể di chuyển hoặc.

(Điều này đúng với tất cả các vùng chứa quản lý bộ nhớ động theo cách thích hợp, chẳng hạn như qua std::allocator<value_type>, nhưng tất nhiên sẽ không đúng đối với một số thứ như std::array và sẽ thú vị cho std::dynarray và như @Jonathan Wakely đã lưu ý, nếu chương trình phân bổ không thể di chuyển các nút bán buôn.)

+4

Di chuyển-gán một bản đồ kiểu 'M' yêu cầu các kiểu phần tử là' MoveInsertable' thành 'M' nếu' allocator_traits :: propagate_on_container_move_assignment :: value' là false –

+0

@JonathanWakely: Oh dear. Vâng, đó là một điểm rất tốt. Tất cả phụ thuộc vào cấp phát! –

+3

Thiết bị phân bổ damn damn damn: - \ –

3

Không có lỗi vì chỉ map được di chuyển, chứ không phải các thành phần của map. Chỉ các con trỏ đến các phần tử được gán

Các vấn đề liên quan