Warum solltevoid
einen unvollständigen Typ sein?
Es gibt viele Gründe.
Am einfachsten ist dies: moo FuncName(...)
noch etwas zurückgeben muss. Ob es ein neutraler Wert ist, ob es der "kein Wertwert" oder was auch immer ist; es muss immer noch return value;
sagen, wobei value
ein tatsächlicher Wert ist. Es muss return moo();
sagen.
Warum eine Funktion schreiben, die technisch etwas zurückgibt, wenn sie tatsächlich nichts zurückgibt? Der Compiler kann die Rückgabe nicht optimieren, da er einen Wert eines vollständigen Typs zurückgibt. Der Anrufer könnte es tatsächlich verwenden.
C++ ist nicht alle Vorlagen, weißt du. Der Compiler hat nicht unbedingt das Wissen, alles wegzuwerfen. Häufig müssen In-Function-Optimierungen durchgeführt werden, die keine Kenntnis von der externen Verwendung dieses Codes haben.
void
bedeutet in diesem Fall bedeutet "Ich gebe nichts zurück." Es besteht ein grundlegender Unterschied zwischen diesem und "Ich gebe einen bedeutungslosen Wert zurück." Es ist legal, dies zu tun:
moo FuncName(...) { return moo(); }
moo x = FuncName(...);
Dies ist bestenfalls irreführend. Ein oberflächlicher Scan legt nahe, dass ein Wert zurückgegeben und gespeichert wird. Der Bezeichner x
hat jetzt einen Wert und kann für etwas verwendet werden.
Während dies:
void FuncName(...) {}
void x = FuncName(...);
ist ein Compiler-Fehler. Das ist also:
void FuncName(...) {}
moo x = FuncName(...);
Es ist klar, was los ist: FuncName
hat keinen Rückgabewert.
Auch wenn Sie C++ entwarfen von Grund auf, ohne Festnahmen von C, würden Sie noch einige Keyword müssen den Unterschied zwischen einer Funktion, um anzuzeigen, die einen Wert und eine zurückgibt, das nicht der Fall ist.
Darüber hinaus ist void*
spezielle in Teil, weil void
ist kein vollständiger Typ. Da der Standard vorschreibt, dass es sich nicht um einen vollständigen Typ handelt, kann das Konzept einer void*
"Zeiger auf nicht typisierten Speicher" bedeuten. Dies hat Casting Semantik spezialisiert. Zeiger auf typisierten Speicher können implizit in nicht typisierten Speicher umgewandelt werden. Zeiger auf nicht typisierten Speicher können explizit in den typisierten Zeiger zurückversetzt werden, der sie einmal war.
Wenn Sie stattdessen moo*
verwendet haben, wird die Semantik merkwürdig. Sie haben einen Zeiger auf typisiert Speicher. Derzeit definiert C++ das Umwandeln von nicht verwandten typisierten Zeigern (mit Ausnahme bestimmter Sonderfälle) zu undefiniertem Verhalten. Jetzt muss der Standard eine weitere Ausnahme für den Typ moo
hinzufügen. Es hat zu sagen, was passiert, wenn Sie dies tun:
moo *m = new moo;
*moo;
Mit void
, dies ist ein Compiler-Fehler ist. Was ist das mit moo
? Es ist immer noch nutzlos und bedeutungslos, aber der Compiler muss es erlauben.
Um ehrlich zu sein, würde ich sagen, dass die bessere Frage wäre "Warum sollte void
eine komplette Art sein?"
Ich stimme mit allem überein, bis auf den letzten Absatz. Die lästigen Spezialfälle, die es beim Umgang mit Templates einführt, sind absichtlich? Wozu? Um Programmierer zu nerven? –
@ R.MartinhoFernandes: Nun, nicht absichtlich, dass es uns ärgert, sondern absichtlich in dem Sinne, dass Ihre Bibliothek in der Lage sein sollte, mit Typen umzugehen, die * nicht instanziiert werden können, wobei "void" das prominenteste Beispiel ist. Zum Beispiel, wenn Sie eine typsichere 'memcpy'-Vorlage geschrieben haben, die im Wesentlichen folgendes tut:' * to = * from'. Wenn du dann 'void' einfügst, * sollte * der Compiler deine Namen nennen, nicht stillschweigend akzeptieren, einfach weil der OP-Dummy-Wert für' void' nicht kopiert worden wäre, was du dir vorgestellt hast! – bitmask
Oh, ich habe es dann falsch verstanden. –