In C muss a nicht in einen void *
anderen Zeigertyp umgewandelt werden, es wird immer sicher heraufgestuft. In C ++ ist dies jedoch nicht der Fall. Z.B,
int *a = malloc(sizeof(int));
funktioniert in C, aber nicht in C ++. (Hinweis: Ich weiß, dass Sie nicht malloc
in C ++ oder für diese Angelegenheit verwenden new
sollten und stattdessen intelligente Zeiger und / oder die STL bevorzugen sollten; dies wird nur aus Neugier gefragt.) Warum erlaubt der C ++ - Standard diese implizite Umwandlung nicht? während der C-Standard tut?
c++
language-features
wolfPack88
quelle
quelle
long *a = malloc(sizeof(int));
Hoppla, jemand hat vergessen, nur einen Typ zu ändern!sizeof(*a)
stattdessen verwenden.malloc
es keinen Zeiger auf den zugewiesenen Typ zurückgeben kann.new
is C ++ gibt einen Zeiger auf den zugewiesenen Typ zurück, sodass ordnungsgemäß geschriebener C ++ - Code niemalsvoid *
s zum Umwandeln hat.void
, C nicht . Wenn das Schlüsselwort / Idee zu C hinzugefügt wurde, sie verändert es C Bedürfnissen gerecht zu werden . Das war kurz nach Zeigertypen gestartet geprüft werden überhaupt . Sehen Sie nach, ob Sie die K & R C-Beschreibungsbroschüre online oder eine Vintage-Kopie eines C-Programmiertexts wie C Primer von Waite Group finden . ANSI C war voll mit Features, die von C ++ zurückportiert oder inspiriert wurden, und K & R C war viel einfacher. Es ist also korrekter, dass C ++ C erweitert hat, wie es zu der Zeit existierte, und dass das C, das Sie kennen, von C ++ entfernt wurde.Antworten:
Weil implizite Typkonvertierungen normalerweise unsicher sind und C ++ eine sicherere Haltung beim Tippen einnimmt als C.
C lässt normalerweise implizite Konvertierungen zu, auch wenn die meisten Chancen bestehen, dass die Konvertierung ein Fehler ist. Dies liegt daran, dass C davon ausgeht, dass der Programmierer genau weiß, was er tut. Andernfalls liegt es am Problem des Programmierers und nicht am Problem des Compilers.
C ++ lässt normalerweise Dinge zu, die möglicherweise Fehler sind, und fordert Sie auf, Ihre Absicht explizit mit einer Typumwandlung zu erklären. Das liegt daran, dass C ++ versucht, programmiererfreundlich zu sein.
Sie könnten fragen, warum es freundlich ist, wenn Sie tatsächlich mehr eingeben müssen.
Wie Sie sehen, wird eine bestimmte Codezeile in jedem Programm, in jeder Programmiersprache im Allgemeinen viel öfter gelesen als geschrieben (*). Das Lesen ist also viel wichtiger als das Schreiben. Und beim Lesen hilft es, potenziell unsichere Konvertierungen durch explizite Typumwandlungen hervorzuheben, um zu verstehen, was vor sich geht, und um ein gewisses Maß an Gewissheit darüber zu haben, dass das, was geschieht, tatsächlich das ist, was geschehen soll.
Außerdem ist die Unannehmlichkeit, die explizite Besetzung eingeben zu müssen, im Vergleich zu der Unannehmlichkeit von Stunden zu Stunden der Fehlersuche, einen Fehler zu finden, der durch eine fehlerhafte Zuweisung verursacht wurde, vor der Sie gewarnt werden konnten, die Sie aber nie hatten.
(*) Idealerweise wird es nur einmal geschrieben, aber jedes Mal, wenn jemand es überprüfen muss, um festzustellen, ob es für die Wiederverwendung geeignet ist, und jedes Mal, wenn eine Fehlerbehebung durchgeführt wird und wenn jemand Code in der Nähe hinzufügen muss, wird es gelesen. und dann jedes Mal gibt es Fehlerbehebung von Code in der Nähe und so weiter. Dies gilt in allen Fällen, mit Ausnahme von Skripten, die nur einmal geschrieben, ausgeführt und dann weggeworfen werden. Kein Wunder, dass die meisten Skriptsprachen eine Syntax haben, die das Schreiben erleichtert, ohne die Lesefreundlichkeit zu beachten. Hast du jemals gedacht, dass Perl völlig unverständlich ist? Du bist nicht allein. Stellen Sie sich solche Sprachen als "Nur-Schreiben" -Sprachen vor.
quelle
void*
ist mehr unsicher in C ++, weil die Art und Weise bestimmte OOP Funktionen in C implementiert werden ++, Zeiger auf gleiches Objekt könnte anderen Wert hat je nach Zeigertyp.Das sagt Stroustrup :
Anschließend zeigt er ein Beispiel, wie leer * gefährlich sein kann und sagt:
Schließlich stellt er fest:
In " Das Design und die Entwicklung von C ++" geht er ausführlicher darauf ein .
Die Antwort lautet also: Der Sprachdesigner ist der Ansicht, dass es sich um ein unsicheres Muster handelt, und hat es daher illegal gemacht und alternative Methoden bereitgestellt, um das zu erreichen, wofür das Muster normalerweise verwendet wurde.
quelle
malloc
Beispiel ist anzumerken, dassmalloc
(offensichtlich) kein Konstruktor aufgerufen wird. Wenn es sich also um einen Klassentyp handelt, für den Sie Speicher zuweisen, wäre es irreführend, implizit in den Klassentyp umgewandelt zu werden.Es wird immer beworben, aber kaum sicher .
C ++ deaktiviert dieses Verhalten genau deshalb, weil versucht wird, ein sichereres Typsystem als C zu verwenden, und dieses Verhalten ist nicht sicher.
Betrachten Sie im Allgemeinen diese drei Ansätze zur Typkonvertierung:
Nun, ich bin hässlich und ein praktisches Hindernis für die Erledigung von Aufgaben, könnte aber auch wirklich dort eingesetzt werden, wo große Sorgfalt geboten ist. C entschied sich grob für 2, was einfacher zu implementieren ist, und C ++ für 3, was schwieriger zu implementieren ist, aber sicherer.
quelle
Per Definition kann ein ungültiger Zeiger auf alles zeigen. Jeder Zeiger kann in einen ungültigen Zeiger konvertiert werden. Auf diese Weise können Sie den exakt gleichen Wert zurückkonvertieren. Zeiger auf andere Typen können jedoch Einschränkungen aufweisen, z. B. Ausrichtungsbeschränkungen. Stellen Sie sich beispielsweise eine Architektur vor, in der Zeichen eine beliebige Speicheradresse belegen können, Ganzzahlen jedoch an geraden Adressgrenzen beginnen müssen. In bestimmten Architekturen können Integer-Zeiger sogar 16, 32 oder 64 Bit gleichzeitig zählen, sodass ein char * tatsächlich ein Vielfaches des numerischen Werts von int * hat, während es auf dieselbe Stelle im Speicher verweist. In diesem Fall würde das Konvertieren von einer Lücke * tatsächlich Bits abrunden, die nicht wiederhergestellt werden können und daher nicht umkehrbar sind.
Einfach ausgedrückt kann der leere Zeiger auf alles zeigen, einschließlich auf Dinge, auf die andere Zeiger möglicherweise nicht zeigen können. Somit ist die Konvertierung in den leeren Zeiger sicher, aber nicht umgekehrt.
quelle