Warnung: übergeben von NULL in nicht-Zeiger-argument für " std::thread::thread
Die Funktion, die ich ausführen möchten:
struct foo;
void bar(const foo* p = 0);
Wie ich die Funktion aufrufen:
auto thread = std::thread(&bar, NULL);
Warnung:
foobar.h:223:9: Warnung: übergeben von NULL in nicht-Zeiger-argument 2 of 'std::thread::thread(_Callable&&, _Args&& ...) [mit _Callable = void (*)(const foo*), _Args = {int}]' [-Wconversion-null]
Was vermisse ich hier?
Wenn ich die Funktion aufrufen mit nicht-NULL
argument, die Warnung geht Weg.
- und wenn Sie
0
stattNULL
? - Sie sollten wirklich mit
nullptr
stattNULL
in C++ >= 11. - Im Aufruf? @Wimmel habe ich geändert, der Prototyp, ist nichts passiert.
- Ich habe zu prüfen, dass @cdhowie, nie benutzt, bevor.
nullptr
scheint, das Problem zu lösen! Ich habe Hinzugefügt, der Zeiger, nachdem ich gelesen habe, dass stackoverflow.com/questions/13888453/.... Auch, werden Sie sich eine Antwort mit, dass? Wenn ja, möchten Sie vielleicht den link zu dieser Frage: stackoverflow.com/questions/1282295/what-exactly-is-nullptr- Die
_Args
Liste fürstd::thread
hat, int, int
für die letzten beiden Parameter. Es sieht für mich wie der compiler verwirrt ist durch die default-Werte oder so etwas. - Richtig @molbdnilo, bemerkte ich, dass auch, aber der Prototyp hat Zeiger als die letzten zwei Argumente (ich habe auch die gleiche Warnung für das Letzte argument). Es wäre schön zu wissen, warum dies passiert ist.
- Nein,
_Args
ist, die sich durch die Argumente geliefert, um diestd::thread
Konstruktor, die impliziert, dass was auch immer dieNULL
makro ausgewertet hat, gebenint
. Die definition vonNULL
wird durch die Implementierung festgelegt, so würden wir wissen, wie es definiert ist in OP ' s Fall, zu verstehen, warum es den Typint
. (In der Regel ist es definiert als((void *)0)
im älteren C-code. Offensichtlich hat er eine andere definition hier -- wahrscheinlich nur0
, und0
implizit konvertierbar jeder Typ Zeiger, aber einige randomint
- das, was der0
wird als parameter anstd::thread()
nicht.) - Ah, ja, natürlich. Es war zu offensichtlich, denke ich.
- Ich sagte: "in älteren C-code". C ist viel entspannter über die Konvertierungen zwischen
void *
und andere Zeiger-Typen, so dass es dort arbeitet. Würde dies nicht funktionieren, in C++, weil es nicht ermöglichen, eine implizite Konvertierung vonvoid *
zu anderen Zeigertypen. - Sind Sie wirklich sicher, dass es nicht definiert ist, dass Art und Weise, in neueren C?
- Ich bekam eine enge Abstimmung, warum? Sollte ich ändern, die Frage für zukünftige Nutzer?
- Das ist eine der möglichen Definitionen ist aber nicht der einzige.
- meine Stimme natürlich), Die Frage ist etwas unvollständig, dass Ihre tatsächlichen Aufruf verwendet eine Reihe von undefinierten Variablen. Auch die definition von
populate
erscheint definieren Sie eine Kostenlose Funktion, die sich nicht auf die member-Funktion&Random_kd_forest::populate
. Und schließlich, sollten Sie ein minimal-Beispiel. Dies kann reproduziert werden, mit nurvoid populate(void*)
. - Ich sehe, ich habe im Hinterkopf, das nächste mal @MSalters! Ich bin sehr verwirrt jetzt auf die Antwort, die ich wählen sollten, scheinen beide einfach gut zu mir!
- Weil der edit-ich wähle deine Antwort @Deduplicator, um zu brechen die Band. 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das Problem ist, dass
NULL
ist ein bisschen zweideutig.Während es semantisch einen Zeiger, es kann (und Ihre Umsetzung) der integral-Typ.
Damit Ihre Umsetzung beschlossen, es schlicht
0
für rückwärts-Kompatibilität, aber zu Kennzeichnen, für die zusätzliche Diagnostik.Was ist eigentlich eine sehr lobenswerte Entscheidung für die Förderung von portablen code.
Aber es ist eine Schande, niemand könne hop in eine Zeit-Maschine und machen
NULL
identischnullptr
im standard, so dass die Mehrdeutigkeit nicht vorhanden.Den Fehler zu beheben, verwenden Sie
nullptr
stattNULL
oder, komplizierter und nicht so schön ist, einen Zeiger des richtigen Typs.NULL
: 1. Es ist in einen Zeiger-Kontext. Alles gut. 2. Es ist eingesetzt in eine nicht-Zeiger-Kontext und definiert alsnullptr_t{}
. Eine Festplatte Fehler. Kann nicht passieren, wenn die empfangende Typ abgeleitet wird, wie für eine Vorlage. 3. Es ist eingesetzt in eine nicht-Zeiger-Kontext und definiert als0
. Dies ist der semantische Fehler, die Warnung ist über. Und es ist wichtig, dass esNULL
, weil die übergabe eines einfachen integer-literal alsint
argument ist etwas zu erwarten.NULL
ist mehrdeutig. Es ist semantisch ein Zeiger wörtlich, ausdrücklich eine null-Zeiger-Konstante. Aber seine Art kann (und wurde in diesem Fall) ein integraler Typ. Was bedeutet, dass das template-argument-Typ abgeleitet wird, um integral-Typ.Args&&...
)Das problem ist, dass
NULL
ist ein makro mit dem Wert 0. Template-argument Abzug abgeleitet, die Art derNULL
alsint
(wie Sie sehen können aus die Ende der Warnung). NochNULL
ist per Konvention verwendet für die pointer-Argumente, nicht integral die Argumente. Damit der compiler warnt Sie, dass Sie vorbei sind eineNULL
argument einerint
parameter. Um alles noch schlimmer machen, dies ist technisch falsch, als dass nicht-const integer-argument " 0 " ist nicht mehr garantiert werden, konvertierbar auf einen null-Zeiger.Die richtige Lösung ist
nullptr
. Dies ist, wie der name schon andeutet, ein Zeiger anstelle eines integer.NULL
ein makro mit dem Wert 0, statt eine von der Implementierung definierte universal-null-pointer-Konstante (das könnte schlicht0
)?NULL
, die null-Zeiger-Konstanten und der definition null-Zeiger-Konstanten, die Liste als eine Möglichkeit ein integral null-literal. Es ist, dass die andere Möglichkeit zu.nullptr
.NULL
war der Kern des Problems.