2009-09-25 40 views
70

dụ giả tạo, vì lợi ích của câu hỏi:Tại sao không phải là toán tử [] const cho các bản đồ STL?

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map[x] << std::endl 
} 

này sẽ không biên dịch, vì toán tử [] là không const.

Điều này là không may, vì cú pháp [] trông rất rõ ràng. Thay vào đó, tôi phải làm một cái gì đó như thế này:

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    std::cout << iter->second << std::endl 
} 

Điều này luôn luôn làm phiền tôi. Tại sao toán tử [] không const?

+4

gì nên 'operator [] 'năng suất trong trường hợp phần tử đã cho không tồn tại? –

+1

@Frerich Raabe: Tương tự như chức năng thành viên: ném tiêu chuẩn :: out_of_range –

Trả lời

76

Đối std::map, operator[] sẽ chèn giá trị chỉ số vào container nếu nó đã làm trước đó không tồn tại. Đó là một chút không trực quan, nhưng đó là cách nó được.

Vì nó phải được phép thất bại và chèn một giá trị mặc định, nhà điều hành không thể được sử dụng trên một phiên bản const của vùng chứa.

http://en.cppreference.com/w/cpp/container/map/operator_at

+1

'std :: set' không có' toán tử [] '. – avakar

+0

Rất tiếc, đúng vậy. Đã chỉnh sửa. – Alan

+0

Đó là câu trả lời đúng, nhưng phiên bản const có thể làm tương tự như thành viên "tại". Đó là ném một std :: out_of_range ... –

0

Toán tử chỉ mục chỉ nên là const cho vùng chứa chỉ đọc (không thực sự tồn tại trong STL mỗi lần).

Toán tử chỉ mục không chỉ được sử dụng để xem xét các giá trị.

+4

Câu hỏi đặt ra là, tại sao nó không có hai phiên bản quá tải - một 'const', một' không 'khác - như ví dụ 'std :: vector'. –

26

Lưu ý cho người đọc mới.
Câu hỏi ban đầu là về các thùng chứa STL (không cụ thể về bản đồ :: bản đồ)

Cần lưu ý rằng có một phiên bản const của toán tử [] trên hầu hết các vùng chứa.
Nó chỉ là std :: map và std :: set không có phiên bản const và đây là kết quả của cấu trúc bên dưới triển khai chúng.

Từ std :: vector

reference  operator[](size_type n) 
const_reference operator[](size_type n) const 

Cũng ví dụ thứ hai của bạn, bạn nên kiểm tra cho một thất bại để tìm nguyên tố này.

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    if (iter != m_map.end()) 
    { 
     std::cout << iter->second << std::endl 
    } 
} 
+0

'std :: set' không có' toán tử [] '. – Everyone

0

Nếu bạn khai báo biến thành viên std :: bản đồ của bạn là có thể thay đổi

mutable std::map<...> m_map; 

bạn có thể sử dụng các hàm thành viên không const của std :: bản đồ trong hàm thành viên const của bạn.

+13

Đây là một ý tưởng khủng khiếp, mặc dù. – GManNickG

+0

Tại sao đây lại là một ý tưởng tồi tệ? –

+6

API cho lớp học của bạn nằm nếu bạn làm điều đó. Hàm này tuyên bố rằng nó là const - có nghĩa là nó sẽ không sửa đổi bất kỳ biến thành viên nào - nhưng trong thực tế nó có thể đang sửa đổi thành viên dữ liệu m_map. – Runcible

3

Vì toán tử [] có thể chèn phần tử mới vào vùng chứa nên nó không thể là hàm thành viên const. Lưu ý rằng định nghĩa toán tử [] cực kỳ đơn giản: m [k] tương đương với (* ((m.insert (giá trị_type (k, dữ liệu_type()))) trước tiên). Nói đúng ra, chức năng thành viên này là không cần thiết: nó chỉ tồn tại để thuận tiện

41

Bây giờ với C++ 11 bạn có thể có một phiên bản sạch bằng cách sử dụng at()

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map.at(x) << std::endl; 
} 
+3

Nếu 'map' có const và non-const' at() 's - tại sao không giống với' operator [] '? với phiên bản const không chèn bất cứ điều gì mà là ném? (Hoặc trả về một tùy chọn, khi std :: tùy chọn làm cho nó thành tiêu chuẩn) – einpoklum

+0

@einpoklum Điểm chính xác của const chủ yếu là kiểm tra thời gian biên dịch tĩnh. Tôi muốn trình biên dịch phàn nàn hơn ném một ngoại lệ vì tôi đã không sử dụng các đối tượng const một cách chính xác. –

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