map <int, int> giá trị mặc định


78
std::map<int,int> mapy;
++mapy[5];

Có an toàn không khi giả định rằng mapy[5]sẽ luôn là 1? Ý tôi là, sẽ mapy[5]luôn nhận giá trị mặc định là 0 trước '++', ngay cả khi không được khai báo rõ ràng, như trong mã của tôi?



Câu trả lời:


124

Ngay sau khi bạn truy cập bản đồ bằng toán tử [], nếu khóa không tồn tại, nó sẽ được thêm vào. Bộ khởi tạo mặc định của kiểu int được gọi - vì vậy nó sẽ nhận giá trị 0.


Theo như tôi đã trải nghiệm, intgiá trị ban đầu của một nguyên thủy chưa được khởi tạo là không xác định - đó có thể là 0 hoặc có thể là -99765521. Đã bao giờ có một intbiến lớp chưa được khởi tạo và có một trong những giá trị kỳ lạ đó xuất hiện trong chương trình của bạn? Điều đó nói rằng, tôi đã thử nghiệm điều này và nó có vẻ hoạt động. #include <stdio.h> #include <map> using namespace std; int main() { map<int,int> m ; for( int i = 0 ; i < 100 ; i++ ) m[i]++ ; for( const pair<int,int>& p : m ) printf( "m[%d] => %d\n", p.first, p.second ) ; }
bobobobo

29
Nó hoạt động theo một cách khác với bạn nghĩ. int x; làm cho x nhận một giá trị không xác định int x = int (); Một lần nữa x nhận được 0 class foo {int x; foo (): x () {}}; foo f; Dưới đây fx sẽ zero
rep_movsd

@bobobobo: Xem câu trả lời của tôi. Việc khởi tạo phức tạp hơn thế và có nhiều "phương thức hoạt động" tùy thuộc vào ngữ cảnh.
Lightness Races in Orbit

Tôi nghĩ rằng các giá trị trong tất cả các vùng chứa được tạo trong heap và giá trị trong heap sẽ được khởi tạo với một giá trị thích hợp. Trong trường hợp này, 0. Có đúng không?
r0ng

1
Trong C ++ bộ nhớ heap và stack được uninitialized - một đối tượng được khởi tạo bởi constructor mặc định của nó - ngôn ngữ có nhà xây dựng mặc định cho kiểu primitive mà khởi tạo chúng để 0 Khi bạn gọi nó một cách đúng đắn Xem bình luận trước đây của tôi
rep_movsd

40

Vâng, nó là an toàn để giả định.

Do đó, bản đồ operator[]được chỉ định: ([map.access])

Hiệu ứng: Nếu không có khóa tương đương xtrong bản đồ, hãy chèn value_type(std::move(x), T())vào bản đồ.
Trả về: Tham chiếu đến mapped_typetương ứng với xin *this.

T()sử dụng khởi tạo giá trị cho tất cả Tngoại trừ void ([expr.type.conv] / 2)khởi tạo giá trị cho một kết quả ban đầu trong khởi tạo bằng 0 ([dcl.init] / 7) .

Do đó, biểu thức đánh giá một tham chiếu đến một đối tượng có giá trị bằng không ([dcl.init] / 5) .

Sau operator++đó, cuộc gọi tăng đối tượng đó thành một và đánh giá thành một.

(Tất cả các tham chiếu đều là C ++ 11.)


2
Không biết tại sao câu trả lời của bạn bị phản đối vì bạn đúng. Đó chính xác là những gì thông số kỹ thuật nói (chỉ cần tự mình kiểm tra).
Hans de Ruiter

9

Có, giá trị mặc định sẽ là giá trị mặc định của loại đó. Nếu bạn muốn một mặc định khác, bạn có thể tạo một lớp hoạt động giống như một int nhưng có một phương thức khởi tạo mặc định khác.


7

Câu trả lời của Rep_Movsd được đơn giản hóa quá mức và có khả năng dẫn đến nhiều quan niệm sai lầm cực kỳ nguy hiểm. Các kiểu dữ liệu ban đầu trong C ++ không có bộ khởi tạo. Louis Brandy đã có một buổi nói chuyện tuyệt vời, trong đó anh ấy thảo luận về nhiều lỗi C ++ phổ biến ở Facebook và sự hiểu lầm về cách hoạt động của std :: map <> [] là một trong những lỗi mà anh ấy đã thảo luận, đây là một nguồn tuyệt vời mặc dù anh ấy không đi vào chi tiết về cách thức hoạt động của std :: map <> [].

Nói chung, int không được khởi tạo và không được xác định giống như tất cả các kiểu nguyên thủy. Điều đó đang được nói khi được sử dụng với std :: map <> [], int có giá trị mặc định bằng 0 được thiết lập thông qua một quá trình gọi là khởi tạo giá trị. Khởi tạo giá trị là một quá trình thực sự hoạt động với các cấu trúc nói chung. Ví dụ,

struct Struct {
Struct() : memberVariable() {}
       int memberVariable;
};

Sẽ luôn khởi tạo số nguyên bằng 0. Nếu các biến thành viên là các kiểu nguyên thủy khác, chúng cũng sẽ có các giá trị khởi tạo cụ thể. Ví dụ: các kiểu sau được khởi tạo, thông qua việc khởi tạo giá trị như vậy:

bool = false
float = 0.0f
enum = (enum type) 0
pointer = null pointer
pointer to member = null member pointer

Hãy cực kỳ cẩn thận khi làm việc với dữ liệu không được khởi tạo rõ ràng. Một điều cuối cùng, hãy xem xét đoạn mã sau

map<string, int> myMap;
cout << myMap["Foo"];

Mã này không chỉ luôn khởi tạo số nguyên thành 0 mà còn chèn số 0 vào bản đồ. Tóm lại, các kiểu dữ liệu nguyên thủy là không xác định nếu không được khởi tạo, nhưng trong một số trường hợp, chẳng hạn như khởi tạo giá trị cấu trúc hoặc bản đồ sẽ khởi tạo dữ liệu nguyên thủy với một giá trị cụ thể.


2
"Kiểu dữ liệu ban đầu trong C ++ không có bộ khởi tạo" Điều này được đơn giản hóa quá mức và có khả năng dẫn đến những quan niệm sai lầm nguy hiểm. "chưa được khởi tạo" Không. Chà, không hoàn toàn. Nó được gọi là khởi tạo mặc định nhưng có kết quả là một giá trị không xác định (C ++ 11 8.5 / 11). "are undefined" Không. Không xác định. "structs" C ++ không có cấu trúc. "khởi tạo giá trị" Đúng. Điểm mấu chốt là kiểu khởi tạo khác nhau được sử dụng. Ngoài ra, bạn có một số dấu phẩy nối trong văn xuôi của bạn.
Các cuộc đua ánh sáng ở Orbit vào

Các kiểu dữ liệu ban đầu không được khởi tạo thành bất kỳ giá trị nào theo mặc định. Chúng không có cấu trúc mặc định. Trong một số trường hợp, chúng có giá trị xây dựng. Sự phân biệt bạn đang cố gắng tạo ra giữa một hành vi không xác định và không xác định là phi lý. Theo tiêu chuẩn C ++ 11, hành vi không xác định được định nghĩa là: "... cấu trúc chương trình không thể chuyển động hoặc có sai sót hoặc dữ liệu sai, mà tiêu chuẩn này không áp đặt yêu cầu nào" về cơ bản có nghĩa là đã xảy ra lỗi trong lôgic hoặc trạng thái và kết quả là không biết. Tôi chưa bao giờ nói cấu trúc là từ C ++.
Rachel Casey

"Sự phân biệt mà bạn đang cố gắng tạo ra giữa một hành vi không xác định và không xác định là phi lý." Tôi đã không phân biệt, tiêu chuẩn đã làm. Nếu bạn cho rằng điều đó là phi lý, tất nhiên bạn có thể phản đối trong danh sách gửi thư của nhóm làm việc ISO.
Các cuộc đua ánh sáng trong quỹ đạo

"Tôi chưa bao giờ nói cấu trúc là từ C ++." Nếu bạn đã biết điều này, thì tại sao bạn lại nói về cấu trúc trong một câu hỏi C ++? Bây giờ điều đó thật phi lý!
Các cuộc đua ánh sáng trong quỹ đạo

1
Không. Không thể tạo cấu trúc trong C ++. Chỉ có thể tạo một lớp bằng structtừ khóa kế thừa . Mã bạn đã hiển thị chứa một lớp . C ++ không có cấu trúc. Đọc thêm: stackoverflow.com/a/36917400/560648 stackoverflow.com/a/34108140/560648
Lightness Races in Orbit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.