2009-02-03 30 views
43

Tôi có một std::map như thế này:Các bản đồ STL có khởi tạo các kiểu nguyên thủy khi chèn không?

map<wstring,int> Scores; 

Nó lưu trữ tên người chơi và điểm số. Khi ai đó nhận được một số điểm tôi chỉ đơn giản sẽ làm gì:

Scores[wstrPlayerName]++; 

Khi không có phần tử trong bản đồ với phím wstrPlayerName nó sẽ tạo ra một, nhưng nó khởi tạo để không hoặc null trước khi thặng dư hoặc là nó lại không xác định ?

Tôi có nên kiểm tra xem phần tử có tồn tại mỗi lần trước khi tăng không?

Trả lời

61

operator [] trông như sau:

Value& map<Key, Value>::operator[](const Key& key); 

Nếu bạn gọi nó với một chính đó là chưa có trong bản đồ, nó sẽ mặc định-xây dựng một thể hiện mới của Value, đặt nó trong bản đồ bên dưới khóa bạn đã chuyển vào và trả lại tham chiếu cho nó. Trong trường hợp này, bạn đã có:

map<wstring,int> Scores; 
Scores[wstrPlayerName]++; 

Giá trị ở đây là int và ints là mặc định-xây dựng là 0, vì nếu bạn khởi tạo chúng với int(). loại nguyên thủy khác được khởi tạo tương tự (ví dụ , kép(), dài(), bool(), vv).

Cuối cùng, mã của bạn đặt một cặp mới (wstrPlayerName, 0) trong bản đồ, sau đó trả về một tham chiếu đến int, mà sau đó bạn tăng. Vì vậy, không cần phải kiểm tra xem phần tử có tồn tại hay không nếu bạn muốn mọi thứ bắt đầu từ 0.

11

Điều này sẽ mặc định xây dựng một phiên bản mới value. Đối với số nguyên, cấu trúc mặc định là 0, do đó, công trình này hoạt động như dự định.

+1

Đối với số nguyên, mặc định * công trình * không thực sự là một điều. Mặc định * khởi tạo * để chúng không được khởi tạo trừ khi chúng tĩnh. Giá trị * giá trị * khởi tạo của các bản đồ, đó là lý do tại sao trong trường hợp các số nguyên bạn nhận được zero-initialization. – juanchopanza

5

Bạn không nên kiểm tra xem mục đó có tồn tại hay không trước khi tăng nó. Toán tử [] thực hiện chính xác những gì bạn cần để làm, như những người khác đã nói.

Nhưng điều gì sẽ xảy ra nếu giá trị được tạo mặc định không hoạt động cho bạn? Trong trường hợp của bạn, cách tốt nhất để tìm ra nếu phần tử đã tồn tại là cố gắng chèn nó vào. Chức năng thành viên insert cho std::map trả về một std::pair<iterator, bool>. Cho dù chèn thành công hay thất bại, yếu tố đầu tiên của cặp sẽ trỏ đến đối tượng mong muốn (hoặc đối tượng mới của bạn, hoặc đối tượng đã xuất hiện). Sau đó bạn có thể thay đổi giá trị của nó khi bạn thấy phù hợp.

4

Cảm ơn sự giúp đỡ.

Vì vậy, std :: bản đồ thiết lập các giá trị nguyên thủy kiểu của họ để 0.

Tôi chỉ băn khoăn vì tôi nghĩ nguyên thủy loại thứ luôn không xác định khi tạo ra.

Nếu tôi viết một cái gì đó như:

int i; 
i++; 

Trình biên dịch cảnh báo với tôi rằng tôi là undefined và khi tôi chạy chương trình nó thường là không bằng không.

+7

Nó thực sự là một tính năng của ngôn ngữ C++. Nếu bạn gọi một cách rõ ràng hàm tạo của int (int i = int()) như std :: map hiện nó sẽ được khởi tạo bằng không. Một int int tôi vẫn sẽ uninitialized. –

+2

thực sự, bởi vì "int i;" sẽ không khởi tạo mặc định int (không giống như các kiểu lớp). nó sẽ để lại giá trị của nó không xác định. giống nhau: struct a {int i; }; Giá trị của << i là không xác định. struct a {a(): i() {} int i; }; Giá trị << i là 0 –

+0

Đợi. Nếu bạn có cấu trúc A {int i; }; và sau đó bạn tạo đối tượng thuộc loại A, ví dụ: Một myA = A(); sau đó myA.i sẽ là 0 vì gọi/sử dụng A() sẽ khởi tạo toàn bộ myA thành 0, do đó nó sẽ là 0. Xem http://en.cppreference.com/w/cpp/language/zero_initialization – Will

1

Kiểm tra quy tắc để khởi tạo.

Xem phần 4.9.5 Khởi tạo C++ Prog Lang hoặc C++ std book. Tùy thuộc vào việc biến của bạn là cục bộ, tĩnh, do người dùng định nghĩa hoặc khởi tạo mặc định có thể xảy ra.

Trong trường hợp này, int được gọi là POD (Kiểu dữ liệu cũ đồng bằng). Bất kỳ tự động nào (được tạo trên biến heap/local) Biến POD không được khởi tạo mặc định. Do đó cho bạn "i" ở trên sẽ không có giá trị bằng không.

Luôn tạo thói quen khởi tạo POD khi được xác định trong heap. Bạn thậm chí có thể sử dụng int() để khởi tạo giá trị.

+3

Những gì bạn đã nói về POD là chính xác, nhưng OP hỏi về khởi tạo được thực hiện bởi std :: map. Câu trả lời của bạn không áp dụng và có thể gây nhầm lẫn cho người đọc vì nó dường như mâu thuẫn với các câu trả lời khác. – MatthewD

+0

Được rồi, câu trả lời của bạn thực sự phản hồi câu trả lời của @ Calmarius, hiện tại là ** dưới đây ** (không ** ở trên **) khi tôi đang đọc nó ngay bây giờ. Điều này thực sự nên là một bình luận ở đó, không phải là một câu trả lời riêng biệt. – MatthewD

+0

Là câu trả lời cho câu hỏi được đăng, điều này hoàn toàn sai. – juanchopanza

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