Frage

Unter welchen Umständen können Sie mehrere indirection verwenden möchten (das heißt, eine Kette von Zeigern wie in Foo **) in C ++?

War es hilfreich?

Lösung

Die häufigsten Verwendung als @aku darauf hingewiesen, ist ein Wechsel zu einem Zeigerparameter zu ermöglichen sichtbar, nachdem die Funktion zurückkehrt zu sein.

#include <iostream>

using namespace std;

struct Foo {
    int a;
};

void CreateFoo(Foo** p) {
    *p = new Foo();
    (*p)->a = 12;
}

int main(int argc, char* argv[])
{
    Foo* p = NULL;
    CreateFoo(&p);
    cout << p->a << endl;
    delete p;
    return 0;
}

Dieses druckt

12

Aber es gibt einige andere nützliche Verwendungen wie im folgenden Beispiel ein Array von Strings iterieren und sie auf die Standardausgabe gedruckt werden.

#include <iostream>

using namespace std;

int main(int argc, char* argv[])
{
    const char* words[] = { "first", "second", NULL };
    for (const char** p = words; *p != NULL; ++p) {
        cout << *p << endl;
    }

    return 0;
}

Andere Tipps

IMO am weitesten verbreitete Anwendung ist Referenz zu übergeben Variable Zeiger

void test(int ** var)
{
 ...
}

int *foo = ...
test(&foo);

Sie können mehrdimensionale erstellen gezackten Array mit Doppelzeiger:

int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];

Ein gängiges Szenario ist, wo Sie brauchen einen null passieren Zeiger auf eine Funktion, und haben sie in dieser Funktion initialisiert und außerhalb der Funktion verwendet. Ohne multplie indirection würde die aufrufende Funktion niemals Zugriff auf das initialisierte Objekt hat.

Betrachten Sie die folgende Funktion:

initialize(foo* my_foo)
{
    my_foo = new Foo();
}

Jede Funktion, die ‚initialisiert werden (foo *)‘ ruft keinen Zugriff auf die initialisierte Instanz von Foo , beacuse der Zeiger, der an diese Funktion übergeben wird ist eine Kopie. (Der Zeiger ist nur eine ganze Zahl nachdem alle, und ganze Zahlen sind von Wert übergeben.)

Wenn jedoch die Funktion wurde wie folgt definiert:

initialize(foo** my_foo)
{
    *my_foo = new Foo();
}

... und es wurde wie folgt aufgerufen ...

Foo* my_foo;

initialize(&my_foo);

... dann würde der Anrufer Zugriff auf die initialisierte Instanz, über ‚my_foo‘ - weil es die Adresse des Zeigers, die zu ‚initialisieren‘ übergeben wurde.

Natürlich in meinem vereinfachten Beispiel die ‚initialisieren‘ -Funktion einfach die neu erstellte Instanz über das Schlüsselwort return zurückkehren konnte, aber das muss nicht immer Anzug -. Vielleicht braucht die Funktion etwas anderes zurück

Wenn Sie einen Zeiger in als Ausgabeparameter übergeben, könnte man es als Foo** übergeben wollen und seinen Wert als *ppFoo = pSomeOtherFoo gesetzt.

Und von der Algorithmen-und-Daten-Strukturen Abteilung, können Sie diese Doppel indirection verwenden Zeiger zu aktualisieren, die schneller als zum Beispiel tatsächliche Objekte tauscht sein können.

Ein einfaches Beispiel wäre mit int** foo_mat als 2D-Array von ganzen Zahlen sein. Oder Sie auch Zeiger auf Zeiger verwenden können - können sagen, dass Sie einen Zeiger void* foo haben, und Sie haben 2 verschiedene Objekte, die einen Verweis auf sie mit den folgenden Mitgliedern: void** foo_pointer1 und void** foo_pointer2, durch einen Zeiger auf einen Zeiger aufweisen, können Sie tatsächlich überprüfen, ob *foo_pointer1 == NULL die anzeigt, dass foo NULL ist. Sie wäre in der Lage, nicht zu prüfen, ob foo NULL ist, wenn foo_pointer1 ein regulärer Zeiger war. Ich hoffe, dass meine Erklärung nicht zu chaotisch war:)

Carl: Ihr Beispiel sollte sein:

*p = x;

(Sie haben zwei Sterne.): -)

In C wird das Idiom unbedingt erforderlich. Betrachten Sie das Problem, in dem Sie eine Funktion wollen einen String hinzufügen (reines C, so dass ein char *) auf ein Array von Zeigern auf char *. Der Funktionsprototyp erfordert drei Dereferenzierungsebenen:

int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);

Wir nennen es wie folgt:

unsigned int   the_count = 0;
char         **the_list  = NULL;

AddStringToList(&the_count, &the_list, "The string I'm adding");

In C ++ haben wir die Möglichkeit, Referenzen stattdessen verwenden, die eine andere Signatur ergeben würden. Aber wir müssen noch die beiden Dereferenzierungsebenen gefragt Sie in Ihrer ursprünglichen Frage zu:

int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);

In der Regel, wenn Sie einen Zeiger auf eine Funktion als Rückgabewert übergeben:

ErrorCode AllocateObject (void **object);

Dabei steht die Funktion einen Erfolg / Mißerfolg Fehlercode zurück und füllt die Objektparameter mit einem Zeiger auf das neue Objekt:

*object = new Object;

Das ist eine Menge in COM-Programmierung in Win32 verwendet.

Dies ist eher ein C, was zu tun, in C ++ Sie oft diese Art von System in eine Klasse wickeln können, um den Code besser lesbar zu machen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top