2009-03-29 29 views
65

See also C++ standard list and default-constructible typesTại sao đối số kiểu bản đồ C++ yêu cầu một hàm tạo rỗng khi sử dụng []?

Không phải là vấn đề lớn, chỉ gây phiền toái vì tôi không muốn lớp học của mình được khởi tạo mà không có các đối số cụ thể.

class MyClass 
{ 
public: 
    MyClass(MyType1 t); 
    MyType2 &operator[](int index); 
} 

map<int, MyClass> myMap; 

này mang lại cho tôi những g sau ++ lỗi:

/usr/include/c++/4.3/bits/stl_map.h:419: error: no matching function for call to ‘MyClass()’

này biên dịch tốt nếu tôi thêm một constructor mặc định; Tôi chắc chắn nó không phải do cú pháp sai.

+0

Đoạn mã trên chỉ biên soạn tốt trên MinGW (g ++ 3.4.5) và MSVC++ 2008, với điều kiện một typedef cho MyType được đưa ra và dấu chấm phẩy được nối vào cuối lớp. Bạn phải làm điều gì khác (ví dụ: nhà điều hành gọi [] như đã đề cập bởi bb) - vui lòng đăng * mã * đầy đủ. –

+0

Ah, vâng, bạn nói đúng. Sẽ làm. –

+0

Vâng, không cần sử dụng myMap bạn không biết cần phải biên dịch gì cho lớp bản đồ. Nhà cung cấp thư viện stl và phiên bản nào cũng có thể hữu ích. –

Trả lời

119

Sự cố này đi kèm với toán tử []. Trích dẫn từ tài liệu SGI:

data_type& operator[](const key_type& k) - Returns a reference to the object that is associated with a particular key. If the map does not already contain such an object, operator[] inserts the default object data_type() .

Nếu bạn không có hàm tạo mặc định, bạn có thể sử dụng chức năng chèn/tìm. Ví dụ sau hoạt động tốt:

myMap.insert(std::map< int, MyClass >::value_type (1, MyClass(1))); 
myMap.find(1)->second; 
+8

Câu trả lời tuyệt vời - cũng lưu ý 'emplace' trong C++ 11 như là một thay thế terse để' chèn'. – prideout

+1

Tại sao 'std :: :: value_type' có trong lệnh gọi' insert'? – thomthom

+0

Tại sao hàm tạo mặc định cần được người dùng xác định? – schuess

6

Có. Giá trị trong các container STL cần phải duy trì ngữ nghĩa sao chép. IOW, chúng cần phải hoạt động như các kiểu nguyên thủy (ví dụ: int), có nghĩa là, trong số những thứ khác, chúng nên được cấu hình mặc định.

Nếu không có yêu cầu (và các yêu cầu khác), sẽ không cần thiết để thực hiện các hoạt động sao chép/di chuyển/hoán đổi/so sánh nội bộ khác nhau trên cấu trúc dữ liệu.

Khi tham chiếu đến tiêu chuẩn C++, tôi thấy câu trả lời của mình không chính xác. Default-xây dựng, trong thực tế, không phải là một yêu cầu:

Từ 20.1.4.1:

The default constructor is not required. Certain container class member function signatures specify the default constructor as a default argument. T() must be a well-defined expression ...

Vì vậy, nói cho đúng, kiểu giá trị của bạn chỉ cần phải được constructible mặc định nếu bạn tình cờ được sử dụng một hàm của vùng chứa sử dụng hàm tạo mặc định trong chữ ký của nó.

Yêu cầu thực tế (23.1.3) từ tất cả các giá trị được lưu trữ trong vùng chứa STL là CopyConstructibleAssignable.

Ngoài ra còn có các yêu cầu cụ thể khác cho các vùng chứa cụ thể, chẳng hạn như là Comparable (ví dụ: đối với các khóa trên bản đồ).


Ngẫu nhiên, sau biên dịch không có lỗi trên comeau:

#include <map> 

class MyClass 
{ 
public: 
    MyClass(int t); 
}; 

int main() 
{ 
    std::map<int, MyClass> myMap; 
} 

Vì vậy, đây có thể là một g ++ vấn đề.

+2

Bạn có nghĩ rằng bb có thể liên quan đến điều gì đó liên quan đến []? –

+10

Mã đó có thể biên dịch vì bạn không gọi myMap [] – jfritz42

-1

Kiểm tra nếu:

  • Bạn quên ';' sau khi khai báo lớp học.
  • MyType phải được khai báo tương ứng.
  • Không có hàm tạo mặc định nào ở đó ...

Báo cáo bản đồ có vẻ đúng, tôi nghĩ vậy.

+0

Biên dịch tốt nếu tôi thêm một hàm tạo mặc định. –

-1

Rất có thể vì std :: pair yêu cầu nó. std :: pair chứa hai giá trị sử dụng ngữ nghĩa giá trị, do đó bạn cần có khả năng khởi tạo chúng mà không cần tham số. Vì vậy, mã sử dụng std :: pair ở nhiều nơi khác nhau để trả về giá trị bản đồ cho người gọi và điều này thường được thực hiện bằng cách tạo một cặp trống và gán các giá trị vào nó trước khi trả về cặp cục bộ.

Bạn có thể thực hiện việc này với các con trỏ thông minh bằng cách sử dụng bản đồ < int, smartptr < MyClass>> nhưng điều đó bổ sung thêm chi phí kiểm tra con trỏ null.

+2

+0. cặp có thể được sử dụng tốt với các loại T và U thiếu các nhà xây dựng mặc định - điều duy nhất không thể được sử dụng trong trường hợp này là cấu trúc mặc định riêng của cặp . Việc triển khai bản đồ không có chất lượng tốt sẽ sử dụng hàm tạo mặc định này vì nó giới hạn những gì K và V có thể. –

2

Yêu cầu kiểm tra loại lưu trữ của stl :: map. Nhiều bộ sưu tập stl yêu cầu loại được lưu trữ chứa một số thuộc tính cụ thể (hàm tạo mặc định, hàm tạo bản sao, v.v.).

Constructor không có đối số là cần thiết bởi stl :: map, bởi vì nó được sử dụng, khi toán tử [] được gọi với khóa mà chưa được bản đồ lưu giữ. Trong trường hợp này toán tử [] chèn mục mới bao gồm khóa và giá trị mới được tạo bằng cách sử dụng hàm tạo parameterless. Và giá trị mới này sau đó được trả về.

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