Notwendigkeit von Zeigerobjekten in Ziel c

7

Eine sehr grundlegende Frage .. aber wirklich sehr wichtig, um die Konzepte zu verstehen .. In C ++ - oder C-Sprachen verwenden wir normalerweise keine Zeigervariablen zum Speichern von Werten. Das heißt, Werte werden einfach wie folgt gespeichert:

%Vor%

Aber hier in ios sdk, in objective c, werden die meisten Objekte, die wir benutzen, initialisiert, indem man einen Zeiger mit ihnen bezeichnet:

%Vor%

So stellt sich mir die Frage, was der Vorteil und die Verwendung von Pointer-Objekten (so nennen wir sie hier, wenn es das ist) nicht korrekt, bitte, sag es) .. Auch werde ich manchmal mit den Grundlagen der Speicherzuweisung verwirrt, wenn ich ein Zeigerobjekt für die Zuweisung verwende. Kann ich überall nach guten Erklärungen suchen?

    
v-i-s-h-a-l 01.08.2013, 10:56
quelle

5 Antworten

15
  

In C ++ - oder C-Sprachen verwenden wir normalerweise keine Zeigervariablen zum Speichern von Werten

Ich würde diesen "oder C" -Teil herausnehmen. C ++ - Programmierer machen die Verwendung von unformatierten Zeigern nicht gern, aber C-Programmierer tun dies nicht. C-Programmierer lieben Zeiger und betrachten sie als unvermeidliche Wunderlösung für alle Probleme. (Nein, nicht wirklich, aber Zeiger sind immer noch sehr häufig in C verwendet.)

  

aber hier in ios sdk, in objective c, werden die meisten Objekte, die wir verwenden, initialisiert, indem man einen Zeiger mit ihnen bezeichnet

Oh, schau genauer hin:

  

die meisten Objekte

Noch näher:

  

Objekte

Sie sprechen also von Objective-C-Objekten, Amirit? (Ignorieren Sie die Subtilität, dass der C-Standard im Wesentlichen alle Werte und Variablen als "Objekt" beschreibt.)

Es sind wirklich nur Objective-C-Objekte, die immer Zeiger in Objective-C sind. Da Objective-C eine strenge Obermenge von C ist, gelten immer noch alle C-Idiome und Programmiertechniken beim Schreiben von iOS-Apps (oder OS X-Apps oder anderen Objective-C-basierten Programmen). Es ist sinnlos, überflüssig, verschwenderisch, und so wird es sogar als ein Fehler angesehen, etwas wie

zu schreiben %Vor%

nur weil wir in Objective-C Land sind. Primitive (oder besser "einfache alte Datentypen" mit C ++ - Terminologie) folgen immer noch der Regel "keinen Zeiger verwenden, wenn nicht benötigt".

  

was ist der Vorteil und die Notwendigkeit der Verwendung von Zeiger-Objekten

Also, warum sind sie notwendig?

Objective-C ist eine objektorientierte und dynamische Sprache. Diese beiden stark verwandten Eigenschaften der Sprache ermöglichen es Programmierern, Technologien wie Polymorphismus zu nutzen, Duck-Typisierung und dynamische Bindung (Ja, das sind Hyperlinks, klicken Sie darauf).

Die Art und Weise, wie diese Features implementiert werden, macht es erforderlich, dass alle Objekte durch einen Zeiger auf sie dargestellt werden. Lassen Sie uns ein Beispiel sehen.

Eine häufige Aufgabe beim Schreiben einer mobilen Anwendung ist das Abrufen einiger Daten von einem Server. Moderne webbasierte APIs verwenden das JSON-Datenaustauschformat zum Serialisieren von Daten. Dies ist ein einfaches Textformat, das (z. B. mit der Klasse NSJSONSerialization ) in verschiedene Arten von Datenstrukturen und ihre entsprechenden Erfassungsklassen (z. B. NSArray oder NSDictionary ) geparst werden kann. Dies bedeutet, dass die JSON-Parser-Klasse / method / function etwas generic, etwas zurückgeben muss, das sowohl als auch ein Wörterbuch darstellen kann.

Also was nun? Wir können keinen non-pointer NSArray oder NSDictionary struct zurückgeben (Objective-C-Objekte sind wirklich nur alte C-Structs unter den Hauben auf allen Plattformen, an denen Objective-C arbeitet), weil sie unterschiedlich groß sind Sie haben unterschiedliche Speicherlayouts usw. Der Compiler konnte den Code nicht verstehen. Deshalb geben wir einen Zeiger auf ein generisches Objective-C Objekt zurück, vom Typ id .

Der C-Standard schreibt vor, dass Zeiger auf struct s (und damit auf Objekte) die gleichen Darstellungs- und Ausrichtungsanforderungen haben (C99 6.2.5.27), d. e. dass ein Zeiger auf irgendeine Struktur in einen Zeiger auf irgendeine andere Struktur sicher umgewandelt werden kann. Daher ist dieser Ansatz korrekt und wir können nun jedes Objekt zurückgeben. Durch Laufzeit-Introspektion kann auch der genaue Typ (Klasse) des Objekts dynamisch bestimmt und dann entsprechend verwendet werden.

Und warum sind sie bequem oder besser (in einigen Aspekten) als Nicht-Zeiger:

Mit Hilfe von Zeigern müssen Sie nicht mehrere Kopien desselben Objekts weitergeben. Das Erstellen vieler Kopien (z. B. jedes Mal, wenn ein Objekt einer Funktion zugewiesen oder an eine Funktion übergeben wird) kann langsam sein und zu Leistungsproblemen führen - ein mäßig komplexes Objekt, z. B. eine Ansicht oder ein Ansichtscontroller, kann dutzende von Kopien enthalten Instanzvariablen, daher kann eine einzelne Instanz buchstäblich Hunderte von Bytes messen. Wenn ein Funktionsaufruf, der einen Objekttyp annimmt, tausende oder Millionen Mal in einer engen Schleife aufgerufen wird, ist das erneute Zuweisen und Kopieren sehr mühsam (für die CPU sowieso), und es ist viel einfacher und einfacher, einfach einen zu übergeben Zeiger auf das Objekt (das kleiner ist und daher schneller kopiert werden kann). Objective-C, eine referenzgezählte Sprache, "ermuntert" sogar irgendwie übermäßiges Kopieren. Das Zurückhalten und Freigeben ist gegenüber dem expliziten Kopieren und Freigeben bevorzugt.

  

Ich werde auch manchmal verwirrt mit Grundlagen der Speicherzuweisung, wenn ein Zeiger Objekte für die Zuordnung verwenden

Dann sind Sie wahrscheinlich sogar genug ohne Zeiger verwirrt. Gib es den Zeigern nicht vor, es ist eher ein Programmierfehler ;-)

Also hier ist ...

Viel Spaß! : -)

    
user529758 01.08.2013, 13:05
quelle
3

Irgendetwas, das komplexer ist als ein int oder ein char oder ähnliches, wird normalerweise als übergeben Zeiger sogar in C. In C könnte man natürlich eine Struktur von Daten weitergeben von Funktion zu Funktion, aber das wird selten gesehen.

Betrachten Sie den folgenden Code:

%Vor%

Die some_struct Daten s werden auf den Stack für function1 gelegt. Wenn Funktion2 heißt die Daten werden kopiert und auf den Stack zur Verwendung in Funktion2 gelegt. Es erfordert, dass die Daten doppelt so gut wie die Daten auf dem Stapel sind kopiert. Dies ist nicht sehr effizient. Beachten Sie auch das Ändern der Werte der Struktur in Funktion2 wird die Struktur in Funktion1 nicht beeinflussen, sie sind unterschiedliche Daten im Speicher.

Betrachten Sie stattdessen den folgenden Code:

%Vor%

Die some_struct-Daten werden anstelle des Stapels auf den Heap gesetzt. Nur Ein Zeiger auf diese Daten wird auf den Stack für Funktion 1 gelegt, kopiert in die Aufruf von Funktion2 ein weiterer Zeiger auf den Stack für Funktion2. Das ist ein Viel effizienter als das vorherige Beispiel. Beachten Sie auch, dass Änderungen von Die Daten in der Struktur, die von function2 erstellt werden, beeinflussen jetzt die Struktur in Funktion1, sie sind die gleichen Daten im Speicher.

Dies sind im Grunde die Grundlagen, auf denen höhere Programmiersprachen stehen wie Objective-C ist gebaut und die Vorteile beim Aufbau dieser Sprachen so.

    
Ernstsson 01.08.2013 12:04
quelle
1

Der Nutzen und die Notwendigkeit des Zeigers ist, dass er sich wie ein Spiegel verhält. Es spiegelt wider, worauf es hinweist. Ein Hauptort, an dem Punkte sehr nützlich sein können, ist das Teilen von Daten zwischen Funktionen oder Methoden. Es ist nicht garantiert, dass die lokalen Variablen ihren Wert bei jeder Rückkehr einer Funktion behalten und dass sie nur innerhalb ihrer eigenen Funktion sichtbar sind. Vielleicht möchten Sie dennoch Daten zwischen Funktionen oder Methoden austauschen. Sie können return verwenden, aber das funktioniert nur für einen einzelnen Wert. Sie können auch globale Variablen verwenden, aber nicht Ihre vollständigen Daten zu speichern, Sie haben bald eine Sauerei. Wir brauchen also eine Variable, die Daten zwischen Funktionen oder Methoden teilen kann. Es gibt Hinweise auf unser Heilmittel. Sie können einfach die Daten erstellen und nur die Speicheradresse (die eindeutige ID) weitergeben, die auf diese Daten verweist. Unter Verwendung dieses Zeigers könnte auf die Daten in jeder Funktion oder Methode zugegriffen und diese geändert werden. In Bezug auf das Schreiben von modularem Code ist das der wichtigste Zweck eines Zeigers, Daten an vielen verschiedenen Stellen in einem Programm zu teilen.

    
Prazad 01.08.2013 11:14
quelle
0

Der Hauptunterschied zwischen C und Objective-C besteht darin, dass Arrays in Objective-C häufig als Objekte implementiert sind. (Arrays werden immer als Objekte in Java implementiert, BTW und C ++ hat mehrere gemeinsame Klassen, die NSArray ähneln.)

Jeder, der das Problem in Betracht gezogen hat, versteht, dass "nackte" C-ähnliche Arrays problematisch sind - umständlich zu handhaben und sehr häufig die Quelle von Fehlern und Verwirrung. ("Ein Array 'zerfällt' zu einem Zeiger '- was soll das eigentlich heißen, außer umgekehrt" Ja, das ist verwirrend "??).

Die Zuweisung in Objective-C ist zu einem großen Teil verwirrend, weil sie sich im Übergang befindet. Das alte manuelle Referenzzählschema könnte leicht verstanden werden (wenn nicht so einfach in Implementierungen behandelt), aber ARC ist zwar einfacher zu handhaben, aber es ist viel schwerer, es wirklich zu verstehen, und beides gleichzeitig zu verstehen ist noch schwieriger. Aber beide sind leichter zu handhaben als C, wo "Zombie-Pointer" aufgrund der fehlenden Referenzzählung fast selbstverständlich sind. (C mag einfacher erscheinen, aber nur, weil Sie keine so komplexen Dinge tun, wie Sie es mit Objective-C tun würden, weil es schwierig ist, alles zu kontrollieren.)

    
Hot Licks 01.08.2013 11:31
quelle
0

Sie verwenden einen Zeiger immer, wenn Sie sich auf etwas auf dem Heap beziehen und manchmal, aber normalerweise nicht, wenn Sie sich auf etwas auf dem Stack beziehen.

Da Objective-C-Objekte immer auf dem Heap zugewiesen sind (mit Ausnahme von Blocks, aber das ist orthogonal zu dieser Diskussion), verwenden Sie immer Zeiger auf Objective-C-Objekte. Sowohl die ID- als auch die Klassen-Typen sind wirklich Zeiger.

Wo Sie keine Zeiger verwenden, sind für bestimmte primitive Typen und einfache Strukturen. Auf NSPoint, NSRange, int, NSUInteger usw. wird normalerweise über den Stack zugegriffen, und normalerweise verwenden Sie keine Zeiger.

    
Christopher Nassar 01.08.2013 12:26
quelle