2012-11-13 38 views
10

Tại sao tôi không được phép đọc một đối tượng từ một unordered_map không đổi?đối tượng đọc từ const unordered_map

const unordered_map<int, int> z; 
int val = z[5]; // compile error 

Các lỗi dưới kêu vang như sau:

error: no viable overloaded operator[] for type 'const 
     unordered_map<int, int>' 
         int val = z[5]; 

Xét rằng mã tương đương sử dụng một const vector hoạt động tốt Tôi hơi bối rối vì sao chúng ta có được hành vi này.

Trả lời

16

Biểu thức z[5] gọi hàm không phải là thành viên của bản đồ.

Điều này là do bản đồ operator[] sẽ chèn một phần tử mới nếu khóa không được tìm thấy, vì vậy rõ ràng nó không phải là const.

Đối với một vector không có gì được chèn bởi operator[], phần tử phải tồn tại (hoặc bạn nhận được hành vi không xác định, vì vậy mã tương đương sẽ truy cập phần tử thứ 6 của một vectơ trống, không tốt!).

Để tra cứu một chìa khóa mà không cần thêm nó sử dụng:

int val = 0; 
auto it = z.find(5); 
if (it != z.end()) 
    val = it->second; 
+7

Để tiết kiệm hơn một chút, bạn cũng có thể sử dụng 'int val = z.at (5);' - Trong trường hợp đó, bạn sẽ nhận được ngoại lệ 'std :: out_of_range' nếu khóa không phải là trong bản đồ. Tất nhiên, nó không ít tiết nếu bạn bao quanh nó trong một khối try-catch. –

+0

Ah vâng tôi quên hành vi này của bản đồ - tôi thấy khá ngạc nhiên khi tìm kiếm một khóa có thể chèn giá trị mặc định vào bản đồ, nhưng điều đó giải thích trong khi đó không phải là hàm thành viên const. Sẽ chấp nhận nó trong 2 phút :) (và có @Benjamin 'at' là sự lựa chọn tốt nhất cho tôi trong mã dù sao đi nữa, bởi vì không tìm thấy giá trị tại thời điểm này sẽ là một lỗi nghiêm trọng). – Voo

+0

@Voo: Nó có thể gây ngạc nhiên ngay từ cái nhìn đầu tiên, nhưng nó ngay lập tức trở nên rõ ràng rằng không có gì khác thực sự có ý nghĩa. –

1

Như Jonathan đã nói, phương pháp operator[] là không const vì nó có thể thêm một giá trị mặc định khi mục nhìn lên không được tìm thấy.

Mặt khác và, như được đánh dấu từ Benjamin trong nhận xét, phương pháp at() cũng có sẵn cho const.

const unordered_map<int, int> z; 
int val = z.at(5); // Success! 

Nhược điểm là khi giá trị nhìn lên không có trong bản đồ, một ngoại lệ std::out_of_range được nâng lên, vì vậy nó phải được quản lý.

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