Zeiger in Python?

123

Ich weiß, dass Python keine Zeiger hat, aber gibt es eine Möglichkeit, 2stattdessen diese Ausbeute zu erzielen ?

>>> a = 1
>>> b = a # modify this line somehow so that b "points to" a
>>> a = 2
>>> b
1

?


Hier ein Beispiel: Ich möchte form.data['field']und form.field.valuesoll immer den gleichen Wert haben. Es ist nicht unbedingt notwendig, aber ich denke, es wäre schön.


In PHP kann ich das zum Beispiel tun:

<?php

class Form {
    public $data = [];
    public $fields;

    function __construct($fields) {
        $this->fields = $fields;
        foreach($this->fields as &$field) {
            $this->data[$field['id']] = &$field['value'];
        }
    }
}

$f = new Form([
    [
        'id' => 'fname',
        'value' => 'George'
    ],
    [
        'id' => 'lname',
        'value' => 'Lucas'
    ]
]);

echo $f->data['fname'], $f->fields[0]['value']; # George George
$f->data['fname'] = 'Ralph';
echo $f->data['fname'], $f->fields[0]['value']; # Ralph Ralph

Ausgabe:

GeorgeGeorgeRalphRalph

ideone


Oder so in C ++ (ich denke das ist richtig, aber mein C ++ ist rostig):

#include <iostream>
using namespace std;

int main() {
    int* a;
    int* b = a;
    *a = 1;
    cout << *a << endl << *b << endl; # 1 1

    return 0;
}
mpen
quelle
28
Vielleicht kann ich eine ähnliche Frage stellen wie S.Lott (aber produktiver): Können Sie uns einen echten Code zeigen, wo Sie dies tun wollten? Vielleicht sogar in einer anderen Sprache, die mehr nach Ihrem Geschmack ist? Es ist wahrscheinlich, dass sich das Problem, das Sie lösen möchten, für eine pythonischere Lösung eignet, und die Konzentration auf "Ich möchte Zeiger" verdeckt die eigentliche Antwort.
Ned Batchelder
8
Es braucht nicht viel Fantasie; Ich kann mir Dutzende Gründe vorstellen, dies zu tun. Es ist einfach nicht so, wie es in zeigerlosen Sprachen wie Python gemacht wird. Sie müssen es in einen Behälter einwickeln, der nicht unveränderlich ist, wie in Matts Antwort.
Glenn Maynard
14
Sie würden keine Swap-Funktion in Python schreiben. Du würdest schreiben a, b = b, a.
dan04
3
-1: Das Konstrukt in der Frage ist (a) sinnlos und (b) niemand scheint in der Lage zu sein, ein Beispiel zu liefern, das es sinnvoll macht. Zu sagen, dass es "Dutzende von Gründen" gibt, ist nicht dasselbe wie ein Beispiel zu veröffentlichen.
S.Lott
1
@ Mark: Außerdem bin ich nicht "anderer Meinung". Ich bin verwirrt. Ich stelle eine Frage und suche nach einer Möglichkeit zu verstehen, was dies ist und warum Sie es für so wichtig halten.
S.Lott

Antworten:

48

Ich möchte form.data['field']und form.field.valuesoll immer den gleichen Wert haben

Dies ist möglich, weil es ergänzte Namen und Indizierung beinhaltet - also völlig unterschiedliche Konstrukte aus der barenames a und bdass Sie fragen über, und für Ihre Anfrage ist völlig unmöglich. Warum fragen Sie nach etwas unmöglich und völlig verschieden von dem (möglichen) , was Sie wirklich wollen ?

Vielleicht merkt man nicht, wie drastisch unterschiedliche Barennamen und dekorierte Namen sind. Wenn Sie sich auf einen Barennamen beziehen a, erhalten Sie genau das Objekt, an adas zuletzt in diesem Bereich gebunden wurde (oder eine Ausnahme, wenn es nicht in diesem Bereich gebunden war) - dies ist ein so tiefer und grundlegender Aspekt von Python, dass dies möglich ist möglicherweise nicht untergraben werden. Wenn Sie sich auf einen dekorierten Namen beziehen, x.ybitten Sie ein Objekt (auf das sich das Objekt xbezieht), "das yAttribut" anzugeben - und als Antwort auf diese Anforderung kann das Objekt völlig willkürliche Berechnungen durchführen (und die Indizierung ist ziemlich ähnlich: es ermöglicht auch die Durchführung beliebiger Berechnungen als Antwort).

Nun ist Ihr Beispiel für "tatsächliche Desiderata" mysteriös, da in jedem Fall zwei Ebenen der Indizierung oder Attributerfassung beteiligt sind, sodass die von Ihnen gewünschte Subtilität auf viele Arten eingeführt werden kann. Welche anderen Attribute form.fieldsollen zum Beispiel daneben haben value? Ohne diese weiteren .valueBerechnungen würden Möglichkeiten umfassen:

class Form(object):
   ...
   def __getattr__(self, name):
       return self.data[name]

und

class Form(object):
   ...
   @property
   def data(self):
       return self.__dict__

Das Vorhandensein von .valueschlägt vor, die erste Form sowie eine Art nutzlosen Wrapper auszuwählen:

class KouWrap(object):
   def __init__(self, value):
       self.value = value

class Form(object):
   ...
   def __getattr__(self, name):
       return KouWrap(self.data[name])

Wenn Zuweisungen wie diese form.field.value = 23auch den Eintrag festlegen sollen, form.datamuss der Wrapper tatsächlich komplexer und nicht allzu nutzlos werden:

class MciWrap(object):
   def __init__(self, data, k):
       self._data = data
       self._k = k
   @property
   def value(self):
       return self._data[self._k]
   @value.setter
   def value(self, v)
       self._data[self._k] = v

class Form(object):
   ...
   def __getattr__(self, name):
       return MciWrap(self.data, name)

Das letztere Beispiel kommt in Python dem Sinn eines "Zeigers" ungefähr so ​​nahe, wie Sie es zu wollen scheinen - aber es ist wichtig zu verstehen, dass solche Feinheiten immer nur mit Indizierung und / oder dekorierten Namen funktionieren können , niemals mit barenamen wie du ursprünglich gefragt hast!

Alex Martelli
quelle
23
Ich habe es so gefragt, wie ich es getan habe, weil ich gehofft hatte, eine allgemeine Lösung zu finden, die für alles bis auf "Barennamen" funktioniert, und ich hatte zu diesem Zeitpunkt keinen bestimmten Fall im Sinn - nur, dass ich darauf gestoßen war Problem mit der vorherigen Iteration dieses Projekts und ich wollte nicht noch einmal begegnen. Auf jeden Fall ist dies eine großartige Antwort! Die Ungläubigkeit wird jedoch weniger geschätzt.
Mpen
2
@Mark, schauen Sie sich die Kommentare zu Ihrem Q an und Sie werden sehen, dass "Ungläubigkeit" eine weit verbreitete Reaktion ist - und das bestbewertete A sagt Ihnen "Tu es nicht, komm darüber hinweg", gefolgt von einem, der geht "es ist einfach so wie es ist". Während Sie Python-fähige Leute, die mit Erstaunen auf Ihre ursprünglichen Spezifikationen reagieren, vielleicht nicht "schätzen", sind sie an sich ziemlich erstaunlich ;-).
Alex Martelli
30
Ja, aber Sie scheinen erstaunt über meinen Mangel an Python-Kenntnissen zu sein ... als wären wir eine fremde Spezies: P
mpen
51

Es gibt keine Möglichkeit, nur diese Zeile zu ändern. Du kannst tun:

a = [1]
b = a
a[0] = 2
b[0]

Das erstellt eine Liste, weist die Referenz a zu, dann verwendet b auch die Referenz a, um das erste Element auf 2 zu setzen, und greift dann mit der Referenzvariablen b zu.

Matthew Flaschen
quelle
17
Das ist genau die Art von Inkonsistenz, die ich an Python und diesen dynamischen Sprachen hasse. (Yeah yeah, es ist nicht wirklich "inkonsistent", weil Sie eher ein Attribut als die Referenz ändern, aber ich mag es immer noch nicht)
mpen
10
@ Mark: in der Tat. Ich kenne unzählige (naja, ein paar) Leute, die möglicherweise Stunden damit verbracht haben, nach einem "Fehler" in ihrem Code zu suchen und dann festzustellen, dass er durch eine Liste verursacht wurde, die nicht hart kopiert wurde.
Houbysoft
14
Es gibt keine Inkonsistenz. Und es hat nichts mit der großen statischen und dynamischen Debatte zu tun. Wenn es sich um zwei Verweise auf dieselbe Java ArrayList handeln würde, wäre dies dieselbe Modulo-Syntax. Wenn Sie unveränderliche Objekte (wie Tupel) verwenden, müssen Sie sich keine Sorgen machen, dass das Objekt durch eine andere Referenz geändert wird.
Matthew Flaschen
Ich habe dies mehrmals verwendet, am häufigsten, um das Fehlen von "nonlocal" in 2.x zu umgehen. Es ist nicht das Schönste, aber es funktioniert zur Not einwandfrei.
Glenn Maynard
1
Dies steht nicht im Widerspruch zu allem , weil das Objekt , das Sie zuweisen aund bdie Liste ist nicht der Wert in der Liste. Die Variablen ändern ihre Zuordnung nicht, das Objekt ist dasselbe Objekt. Wenn es sich ändert, wie im Fall der Änderung der Ganzzahl (von denen jedes ein anderes Objekt ist), wird aes jetzt einem anderen Objekt zugewiesen, und es gibt keine Aufforderung, diesem Beispiel bzu folgen. Hier awird nicht neu zugewiesen, sondern ein Wert innerhalb des Objekts, dem es zugewiesen ist, ändert sich. Da bes immer noch an dieses Objekt gebunden ist, werden dieses Objekt und die Änderungen an den darin enthaltenen Werten wiedergegeben.
Arkigos
34

Es ist kein Fehler, es ist ein Feature :-)

Wenn Sie sich den Operator '=' in Python ansehen, denken Sie nicht an die Zuweisung. Sie weisen keine Dinge zu, Sie binden sie. = ist ein Bindungsoperator.

In Ihrem Code geben Sie dem Wert 1 einen Namen: a. Dann geben Sie dem Wert in 'a' einen Namen: b. Dann binden Sie den Wert 2 an den Namen 'a'. Der an b gebundene Wert ändert sich bei dieser Operation nicht.

Aus C-ähnlichen Sprachen kommend, kann dies verwirrend sein, aber sobald Sie sich daran gewöhnt haben, werden Sie feststellen, dass es Ihnen hilft, Ihren Code klarer zu lesen und zu begründen: Der Wert mit dem Namen 'b' ändert sich nur, wenn Sie explizit ändern. Und wenn Sie dies importieren, werden Sie feststellen, dass das Zen von Python besagt, dass Explizit besser als implizit ist.

Beachten Sie auch, dass funktionale Sprachen wie Haskell dieses Paradigma ebenfalls verwenden, was hinsichtlich der Robustheit von großem Wert ist.

David Harks
quelle
39
Weißt du, ich habe Antworten wie diese Dutzende Male gelesen und ich habe sie nie verstanden. Das Verhalten von a = 1; b = a; a = 2;ist in Python, C und Java genau das gleiche: b ist 1. Warum ist dieser Fokus auf "= ist keine Zuweisung, es ist bindend"?
Ned Batchelder
4
Sie weisen Dinge zu. Deshalb wird es eine Zuweisungsanweisung genannt . Die Unterscheidung, die Sie angeben, macht keinen Sinn. Und das hat nichts mit kompilierter v. Interpretierter oder statischer v. Dynamischer zu tun. Java ist eine kompilierte Sprache mit statischer Typprüfung und hat auch keine Zeiger.
Matthew Flaschen
3
Was ist mit C ++? "b" könnte ein Verweis auf "a" sein. Das Verständnis des Unterschieds zwischen Zuweisung und Bindung ist entscheidend, um vollständig zu verstehen, warum Mark nicht das tun kann, was er möchte, und wie Sprachen wie Python entworfen werden. Konzeptionell (nicht unbedingt in der Implementierung) überschreibt "a = 1" den Speicherblock mit dem Namen "a" nicht mit 1; es weist dem bereits vorhandenen Objekt "1" einen Namen "a" zu, der sich grundlegend von dem unterscheidet, was in C passiert. Deshalb können Zeiger als Konzept in Python nicht existieren - sie würden beim nächsten Mal veraltet sein Die ursprüngliche Variable wurde "zugewiesen über".
Glenn Maynard
1
@dw: Ich mag diese Art, darüber nachzudenken! "Bindung" ist ein gutes Wort. @Ned: Die Ausgabe ist die gleiche, ja, aber in C der Wert von „1“ auf beide kopiert aund bwährend in Python, sie beide beziehen sich auf die gleichen „1“ (glaube ich). Wenn Sie also den Wert 1 ändern könnten (wie bei Objekten), wäre dies anders. Was zu einigen seltsamen Box- / Unboxing-Problemen führt, höre ich.
Mpen
4
Der Unterschied zwischen Python und C ist nicht das, was "Zuweisung" bedeutet. Es ist das, was "Variable" bedeutet.
dan04
28

Ja! Es gibt eine Möglichkeit, eine Variable als Zeiger in Python zu verwenden!

Es tut mir leid zu sagen, dass viele Antworten teilweise falsch waren. Im Prinzip teilt sich jede gleiche (=) Zuweisung die Speicheradresse (überprüfen Sie die ID (obj) -Funktion), in der Praxis ist dies jedoch nicht der Fall. Es gibt Variablen, deren gleiches ("=") Verhalten im letzten Term als Kopie des Speicherplatzes fungiert, hauptsächlich in einfachen Objekten (z. B. "int" -Objekt) und in anderen, in denen dies nicht der Fall ist (z. B. "list" -, "dict" -Objekte). .

Hier ist ein Beispiel für die Zeigerzuweisung

dict1 = {'first':'hello', 'second':'world'}
dict2 = dict1 # pointer assignation mechanism
dict2['first'] = 'bye'
dict1
>>> {'first':'bye', 'second':'world'}

Hier ist ein Beispiel für die Zuweisung von Kopien

a = 1
b = a # copy of memory mechanism. up to here id(a) == id(b)
b = 2 # new address generation. therefore without pointer behaviour
a
>>> 1

Die Zeigerzuweisung ist ein ziemlich nützliches Werkzeug für das Aliasing ohne Verschwendung von zusätzlichem Speicher, in bestimmten Situationen für die Ausführung von komfortablem Code.

class cls_X():
   ...
   def method_1():
      pd1 = self.obj_clsY.dict_vars_for_clsX['meth1'] # pointer dict 1: aliasing
      pd1['var4'] = self.method2(pd1['var1'], pd1['var2'], pd1['var3'])
   #enddef method_1
   ...
#endclass cls_X

Man muss sich dieser Verwendung jedoch bewusst sein, um Codefehler zu vermeiden.

Abschließend sind einige Variablen standardmäßig Barennamen (einfache Objekte wie int, float, str, ...) und einige Zeiger, wenn sie zwischen ihnen zugewiesen werden (z. B. dict1 = dict2). Wie erkennt man sie? Probieren Sie einfach dieses Experiment mit ihnen. In IDEs mit variablem Explorer scheint das Bedienfeld normalerweise die Speicheradresse ("@axbbbbbb ...") in der Definition von Zeigermechanismusobjekten zu sein.

Ich schlage vor, im Thema zu untersuchen. Es gibt viele Leute, die sicher viel mehr über dieses Thema wissen. (siehe Modul "ctypes"). Ich hoffe es ist hilfreich. Genießen Sie die gute Nutzung der Objekte! Grüße, José Crespo

José Crespo Barrios
quelle
Ich muss also ein Wörterbuch verwenden, um eine Variable als Referenz auf eine Funktion zu übergeben, und ich kann eine Variable nicht als Referenz mit einem int oder einer Zeichenfolge übergeben?
Sam
13
>> id(1)
1923344848  # identity of the location in memory where 1 is stored
>> id(1)
1923344848  # always the same
>> a = 1
>> b = a  # or equivalently b = 1, because 1 is immutable
>> id(a)
1923344848
>> id(b)  # equal to id(a)
1923344848

Wie Sie sehen können aund bnur zwei verschiedene Namen sind, die auf dasselbe unveränderliche Objekt (int) verweisen 1. Wenn Sie später schreiben a = 2, weisen Sie den Namen aeinem anderen Objekt (int) zu 2, aber das bverweist weiterhin auf 1:

>> id(2)
1923344880
>> a = 2
>> id(a)
1923344880  # equal to id(2)
>> b
1           # b hasn't changed
>> id(b)
1923344848  # equal to id(1)

Was würde passieren, wenn Sie stattdessen ein veränderbares Objekt wie eine Liste hätten [1]?

>> id([1])
328817608
>> id([1])
328664968  # different from the previous id, because each time a new list is created
>> a = [1]
>> id(a)
328817800
>> id(a)
328817800 # now same as before
>> b = a
>> id(b)
328817800  # same as id(a)

Wiederum verweisen wir auf dasselbe Objekt (Liste) [1]mit zwei verschiedenen Namen aund b. Aber jetzt können wir diese Liste mutieren , während sie das gleiche Objekt bleibt, und a, bwerden beide weiterhin darauf verweisen

>> a[0] = 2
>> a
[2]
>> b
[2]
>> id(a)
328817800  # same as before
>> id(b)
328817800  # same as before
Andreas K.
quelle
1
Vielen Dank für die Einführung der ID-Funktion. Dies löst viele meiner Zweifel.
Haudoing
12

Aus einer Sicht ist in Python alles ein Zeiger. Ihr Beispiel funktioniert sehr ähnlich wie der C ++ - Code.

int* a = new int(1);
int* b = a;
a = new int(2);
cout << *b << endl;   // prints 1

(Ein näheres Äquivalent würde eine Art von shared_ptr<Object>anstelle von verwenden int*.)

Hier ein Beispiel: Ich möchte, dass form.data ['field'] und form.field.value immer den gleichen Wert haben. Es ist nicht unbedingt notwendig, aber ich denke, es wäre schön.

Sie können dies tun, indem Sie __getitem__in form.datader Klasse überladen .

dan04
quelle
form.dataist keine Klasse. Ist es notwendig, es zu einem zu machen, oder kann ich es im laufenden Betrieb überschreiben? (Es ist nur ein Python-Diktat) Außerdem müssten Daten einen Verweis auf haben, formum auf die Felder zugreifen zu können ... was die Implementierung dieses hässlich macht.
Mpen
1

Dies ist ein Python-Zeiger (anders als c / c ++)

>>> a = lambda : print('Hello')
>>> a
<function <lambda> at 0x0000018D192B9DC0>
>>> id(a) == int(0x0000018D192B9DC0)
True
>>> from ctypes import cast, py_object
>>> cast(id(a), py_object).value == cast(int(0x0000018D192B9DC0), py_object).value
True
>>> cast(id(a), py_object).value
<function <lambda> at 0x0000018D192B9DC0>
>>> cast(id(a), py_object).value()
Hello
Henry
quelle
0

Ich habe die folgende einfache Klasse geschrieben, um einen Zeiger in Python effektiv zu emulieren:

class Parameter:
    """Syntactic sugar for getter/setter pair
    Usage:

    p = Parameter(getter, setter)

    Set parameter value:
    p(value)
    p.val = value
    p.set(value)

    Retrieve parameter value:
    p()
    p.val
    p.get()
    """
    def __init__(self, getter, setter):
        """Create parameter

        Required positional parameters:
        getter: called with no arguments, retrieves the parameter value.
        setter: called with value, sets the parameter.
        """
        self._get = getter
        self._set = setter

    def __call__(self, val=None):
        if val is not None:
            self._set(val)
        return self._get()

    def get(self):
        return self._get()

    def set(self, val):
        self._set(val)

    @property
    def val(self):
        return self._get()

    @val.setter
    def val(self, val):
        self._set(val)

Hier ist ein Anwendungsbeispiel (von einer Jupyter-Notizbuchseite):

l1 = list(range(10))
def l1_5_getter(lst=l1, number=5):
    return lst[number]

def l1_5_setter(val, lst=l1, number=5):
    lst[number] = val

[
    l1_5_getter(),
    l1_5_setter(12),
    l1,
    l1_5_getter()
]

Out = [5, None, [0, 1, 2, 3, 4, 12, 6, 7, 8, 9], 12]

p = Parameter(l1_5_getter, l1_5_setter)

print([
    p(),
    p.get(),
    p.val,
    p(13),
    p(),
    p.set(14),
    p.get()
])
p.val = 15
print(p.val, l1)

[12, 12, 12, 13, 13, None, 14]
15 [0, 1, 2, 3, 4, 15, 6, 7, 8, 9]

Natürlich ist es auch einfach, diese Funktion für diktierte Elemente oder Attribute eines Objekts zu verwenden. Es gibt sogar eine Möglichkeit, mit globals () das zu tun, wonach das OP gefragt hat:

def setter(val, dict=globals(), key='a'):
    dict[key] = val

def getter(dict=globals(), key='a'):
    return dict[key]

pa = Parameter(getter, setter)
pa(2)
print(a)
pa(3)
print(a)

Dies druckt 2 aus, gefolgt von 3.

Auf diese Weise mit dem globalen Namespace zu spielen, ist eine schreckliche Idee, aber es zeigt, dass es möglich ist (wenn nicht ratsam), das zu tun, was das OP verlangt.

Das Beispiel ist natürlich ziemlich sinnlos. Ich habe jedoch festgestellt, dass diese Klasse in der Anwendung, für die ich sie entwickelt habe, nützlich ist: ein mathematisches Modell, dessen Verhalten von zahlreichen vom Benutzer einstellbaren mathematischen Parametern verschiedener Typen bestimmt wird (die, da sie von Befehlszeilenargumenten abhängen, nicht bekannt sind zur Kompilierungszeit). Und sobald der Zugriff auf etwas in einem Parameter-Objekt gekapselt wurde, können alle diese Objekte auf einheitliche Weise bearbeitet werden.

Obwohl es nicht viel wie ein C- oder C ++ - Zeiger aussieht, löst dies ein Problem, das ich mit Zeigern gelöst hätte, wenn ich in C ++ geschrieben hätte.

Leon Avery
quelle
0

Der folgende Code emuliert genau das Verhalten von Zeigern in C:

from collections import deque # more efficient than list for appending things
pointer_storage = deque()
pointer_address = 0

class new:    
    def __init__(self):
        global pointer_storage    
        global pointer_address

        self.address = pointer_address
        self.val = None        
        pointer_storage.append(self)
        pointer_address += 1


def get_pointer(address):
    return pointer_storage[address]

def get_address(p):
    return p.address

null = new() # create a null pointer, whose address is 0    

Hier sind Anwendungsbeispiele:

p = new()
p.val = 'hello'
q = new()
q.val = p
r = new()
r.val = 33

p = get_pointer(3)
print(p.val, flush = True)
p.val = 43
print(get_pointer(3).val, flush = True)

Jetzt ist es an der Zeit, einen professionelleren Code anzugeben, einschließlich der Option zum Löschen von Zeigern, die ich gerade in meiner persönlichen Bibliothek gefunden habe:

# C pointer emulation:

from collections import deque # more efficient than list for appending things
from sortedcontainers import SortedList #perform add and discard in log(n) times


class new:      
    # C pointer emulation:
    # use as : p = new()
    #          p.val             
    #          p.val = something
    #          p.address
    #          get_address(p) 
    #          del_pointer(p) 
    #          null (a null pointer)

    __pointer_storage__ = SortedList(key = lambda p: p.address)
    __to_delete_pointers__ = deque()
    __pointer_address__ = 0 

    def __init__(self):      

        self.val = None 

        if new.__to_delete_pointers__:
            p = new.__to_delete_pointers__.pop()
            self.address = p.address
            new.__pointer_storage__.discard(p) # performed in log(n) time thanks to sortedcontainers
            new.__pointer_storage__.add(self)  # idem

        else:
            self.address = new.__pointer_address__
            new.__pointer_storage__.add(self)
            new.__pointer_address__ += 1


def get_pointer(address):
    return new.__pointer_storage__[address]


def get_address(p):
    return p.address


def del_pointer(p):
    new.__to_delete_pointers__.append(p)

null = new() # create a null pointer, whose address is 0
MikeTeX
quelle
Ich denke, Sie haben die Werte nur auf seltsame Weise verpackt.
Mpen
Du meinst: einen "klugen Weg" oder einen "nicht klugen Weg"?
MikeTeX
Uhhh ... Ich habe Probleme, einen gültigen Anwendungsfall für einen globalen Speicher zu finden, der durch eine Zufallszahl indiziert ist.
Mpen
Anwendungsbeispiel: Ich bin Algorithmusingenieur und muss mit Programmierern arbeiten. Ich arbeite mit Python und sie arbeiten mit C ++. Manchmal bitten sie mich, einen Algorithmus für sie zu schreiben, und ich schreibe ihn der Einfachheit halber so nah wie möglich an C ++. Zeiger sind nützlich, zB für binäre Bäume usw.
MikeTeX
Hinweis: Wenn der globale Speicher Probleme verursacht, können Sie ihn als globale Variable auf der Ebene der Klasse selbst einfügen, was wahrscheinlich eleganter ist.
MikeTeX