2013-08-13 75 views
7

Tôi đang biên soạn với g ++ 4.4.7 (và không thể chuyển bất kỳ giá trị nào cao hơn hiện tại), và sử dụng công tắc trình biên dịch -std=gnu++0x, điều này sẽ cho phép cú pháp của hàng.C++ không thể khởi tạo một con trỏ trong một cặp thành NULL

typedef std::vector<CI_RecordInfo_Pair> CI_RecordInfo_Vector; 
typedef std::vector<std::pair<std::string, CI_RecordInfo_Vector*> > MgrBlks; 
MgrBlks mgr_n_blks { {"T2M_NAME", NULL} }; // <--- line 59 

Tuy nhiên, trình biên dịch phàn nàn như sau:

/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h: In constructor 'std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = const char (&)[9], _U2 = long int, _T1 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = CI_RecordInfo_Vector*]': 
tom.cpp:59: instantiated from here 
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h:90: error: invalid conversion from 'long int' to 'CI_RecordInfo_Vector*' 

Tôi giả sử "int dài" là NULL, và rằng đối với một số lý do tôi không thể chuyển nó sang một con trỏ. Tuy nhiên, ở một nơi khác trong bản đồ cấu trúc, tôi đã có thể biên dịch một số thứ như

foo["X"] = { NULL, "bar", 12 }; // first element is a pointer 

Sự khác biệt là gì?

+4

Không sử dụng 'nullptr' thay vì công việc' NULL'? –

+0

Nó không được hỗ trợ bởi g ++ 4.4. Không đến 4.6. – Chap

Trả lời

14

Trình biên dịch là chính xác để từ chối dòng này:

MgrBlks mgr_n_blks { {"T2M_NAME", NULL} }; 

Trong C++ 11 std::pair có một mẫu nhà xây dựng mà phải mất bất kỳ loại đối số, sau đó chuyển đổi chúng sang các thành viên:

template<typename X, typename Y> 
    pair(X&& x, Y&& y) 
    : first(std::forward<X>(x)), second(std::forward<Y>(y)) 
    { } 

NULL phải được định nghĩa là 0 hoặc 0L hoặc một cái gì đó tương tự, do đó, trích đối số mẫu khấu trừ các đối số mẫu của hàm tạo là const char* và (với GCC) long. Loại đối số đầu tiên có thể chuyển đổi thành std::string nhưng long không thể chuyển đổi thành CI_RecordInfo_Vector*, do đó hàm tạo không thể được gọi. Đối với trường hợp khác với bản đồ cấu trúc không có trích dẫn đối số, RHS của nhiệm vụ phải chuyển đổi thành kiểu cấu trúc và trong trường hợp đó NULL được sử dụng để khởi tạo trực tiếp thành viên đầu tiên của cấu trúc, thay vì trước tiên được suy ra như là một long và khởi tạo một long, mà không thể được chuyển đổi thành một con trỏ.

Không sử dụng NULL trong C++ 11, nullptr được phát minh để tránh chính xác những sự cố này, bạn nên sử dụng nó.

Một cách giải quyết có thể sẽ bỏ lập luận theo đúng loại hình:

MgrBlks mgr_n_blks { {"T2M_NAME", (CI_RecordInfo_Vector*)NULL} }; 

nhưng nó đơn giản hơn và rõ ràng hơn chỉ để sử dụng nullptr.

+0

+1 để chỉ định nullptr thay cho NULL với C++ –

+0

mới hơn Nếu 'NULL' được định nghĩa là' 0', thì đó là kiểu 'int', không phải' long'. Rõ ràng việc thực hiện định nghĩa 'NULL' là' 0L' hoặc một cái gì đó tương tự. Với g ++ 4.7.2, 'NULL' mở rộng thành' __null', mà rõ ràng là kiểu 'long'. –

+0

nullptr không được thêm vào cho đến khi g ++ 4.6, nhưng đúc NULL biên dịch chính xác. – Chap