2013-08-13 12 views
7

Ich kompiliere mit g ++ 4.4.7 (und kann derzeit nicht höher gehen), und verwenden Sie den -std=gnu++0x Compiler-Schalter, der die Syntax des dritten ermöglichen sollte Linie.C++ kann einen Zeiger in einem Paar nicht initialisieren 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 

Allerdings wirft der Compiler wie folgt:

/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*' 

ich die „long int“ annehmen, die NULL ist, und dass aus irgendeinem Grund bin ich nicht in der Lage, es zu einem Zeiger zu konvertieren. Aber anderswo in einer Karte von Strukturen konnte ich etwas wie

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

kompilieren Was ist der Unterschied?

+4

Funktioniert 'nullptr' anstelle von' NULL'? –

+0

Es wird nicht von g ++ 4.4 unterstützt. Nicht vor dem 4.6. – Chap

Antwort

14

Der Compiler ist richtig, diese Linie zu verwerfen:

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

In C++ 11 std::pair hat eine Schablone Konstruktor, der alle Argumenttypen annimmt, dann setzt sie den Mitgliedern:

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

NULL muss als 0 oder 0L oder etwas Ähnliches definiert werden, sodass die Argumentableitung des Konstruktors die Vorlagenargumente des Konstruktors als und (mit GCC)ableitet 10. Der erste Argumenttyp ist in std::string konvertierbar, aber long ist nicht in CI_RecordInfo_Vector* konvertierbar, sodass der Konstruktor nicht aufgerufen werden kann. Für den anderen Fall mit einer Strukturabbildung gibt es keinen Argumentabzug, der RHS der Zuweisung muss in den Strukturtyp konvertierbar sein, und in diesem Fall wird NULL verwendet, um das erste Element der Struktur direkt und nicht zuerst zu initialisieren abgeleitet als long und initialisiert eine long, die nicht in einen Zeiger umgewandelt werden kann.

Verwenden Sie nicht NULL in C++ 11, nullptr wurde erfunden, um genau diese Probleme zu vermeiden, sollten Sie es verwenden.

Eine mögliche Abhilfe wäre das Argument der richtigen Art zu werfen:

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

aber es ist einfacher und klarer nur nullptr zu verwenden.

+0

+1 für die Angabe von nullptr anstelle von NULL mit neueren C++ –

+0

Wenn 'NULL' als' 0' definiert ist, dann ist es vom Typ 'int', nicht' long'. Anscheinend definiert die Implementierung "NULL" als "0L" oder etwas Ähnliches. Mit g ++ 4.7.2 erweitert sich 'NULL' zu' __null', was offensichtlich vom Typ 'long' ist. –

+0

nullptr wurde nicht vor g ++ 4.6 hinzugefügt, aber NULL-Umwandlung wird korrekt kompiliert. – Chap

Verwandte Themen