3 Stimmen

C++ private konstante Zeiger

Ich lerne gerade Zeiger in C++ und habe einige Schwierigkeiten. Ich habe eine Klasse Foo die in der Header-Datei einige Daten deklariert:

private:
const Bar *obj;

Wo Bar ist eine Klasse.

Dann möchte ich in der C++-Implementierung Folgendes ersetzen *obj so dass sie auf eine völlig andere Bar Objekt. *obj ist konstant, wie kann ich also ändern, was in was ist? *obj zeigt auf bzw. was im Speicher ist bei *obj ? Auch in Foo Destruktor, wie kann ich die Zuordnung von *obj ?

4voto

jogojapan Punkte 65439

Angesichts Ihrer Klassendefinition

class A {
private:
  const Bar *obj;
};

obj ist ein Zeiger auf eine Konstante Bar Objekt. Sie können ändern, worauf dieser Zeiger zeigt, aber Sie können nicht den Inhalt des Objekts ändern, auf das er zeigt.

Wenn Sie also ein neues Bar Objekts und Sie möchten Folgendes ändern obj so dass er darauf verweist, können Sie einfach den neuen Wert zuweisen:

/* New object: */
Bar *new_bar = new Bar;
/* Change the pointer: */
obj = new_bar;

Es gibt jedoch zwei Probleme.

  1. Wenn die neue Bar Objekt wird erstellt außerhalb der Klasse können Sie es nicht direkt zuordnen obj denn letztere ist privat . Daher benötigen Sie eine Setter-Funktion:

    class A {
    private:
      const Bar *obj;
    public:
      void set_obj(const Bar *new_obj) { obj = new_obj; }
    };
  2. Sie müssen festlegen, wem das Produkt letztendlich gehören wird Bar Objekt d.h. wer für die Freigabe des beanspruchten Heap-Speicherplatzes verantwortlich ist. Wenn der Aufrufer verantwortlich ist, können Sie es wie oben kodieren, d.h. class A wird niemals neue Bar Objekte noch löschen. Es wird lediglich ein Zeiger auf Bar Objekte, die außerhalb der Klasse erstellt und gelöscht werden.

    Aber wenn class A ist eigentlich für den Speicherplatz verantwortlich, den das Programm Bar Objekte, müssen Sie delete obj im Destruktor, um den Platz freizugeben, und Sie müssen den Platz auch freigeben, wenn Sie eine neue Bar Objekt zugeordnet. Das heißt, die set_obj Funktion muss in diese geändert werden:

    void set_obj(const Bar *new_obj) { delete obj; obj = new_obj; }

    Andernfalls kommt es zu einem Speicherleck. Ähnliche Maßnahmen müssen für den Kopierkonstruktor (sofern Sie ihn nicht löschen) und den Zuweisungsoperator getroffen werden: Beide Funktionen werden immer dann verwendet, wenn ein kopieren. eines class A Objekt gemacht wird, und in diesem Fall müssen Sie darauf achten, dass Sie nicht einfach kopieren den Zeiger, sondern weisen Sie stattdessen neuen Speicherplatz zu und kopieren Sie das Objekt (d.h. Sie müssen eine Deep Copy durchführen):

    A(const A& a):obj(new Bar(*a.obj)) {}
    A& operator=(const A& a) { delete obj; obj = new Bar(*a.obj); return *this; }

    Wenn Ihre Klasse jedoch für den Speicherplatz verantwortlich ist, ist es eine viel besser Idee, eine Smart-Pointer-Klasse anstelle eines Raw Pointers zu verwenden. Die Hauptgründe sind: (i) Die obige Methode ist ziemlich kompliziert und man kann leicht Fehler machen; (ii) Die obige Methode ist immer noch nicht sehr gut - es kann immer noch zu Speicherlecks oder schlimmeren Problemen kommen, wenn eine Ausnahme ausgelöst wird, z. B. im Konstruktor von Bar . C++11 bietet eine Smart-Pointer-Klasse namens std::unique_ptr was für Ihre Zwecke ideal zu sein scheint:

    class A {
    private:
      std::unique_ptr<const Bar> obj;
    public:
      ~A() {}
      void set_obj(std::unique_ptr<const Bar> new_obj) { obj = new_obj; }
    };

    Damit kümmert sich der intelligente Zeiger um jeden Speicherplatz, der automatisch freigegeben werden muss, sowohl zum Zeitpunkt der Zerstörung als auch wenn eine neue Bar Objekt wird dem Zeiger zugewiesen.

1voto

dmastylo Punkte 851

Sie können diesen Zeiger nicht verwenden, um den Wert zu ändern, auf den er zeigt, deshalb ist er eine Konstante, aber Sie sollten in der Lage sein, zu ändern, worauf er zeigt.

1voto

imreal Punkte 9958

In C++ bedeutet "const Bar *obj;", dass Sie einen Zeiger auf ein schreibgeschütztes Bar-Objekt haben; das bedeutet, dass Sie auf ein beliebiges schreibgeschütztes Bar-Objekt zeigen können.

Sie können auch auf eine nicht konstante Variable zeigen und damit versprechen, dass Sie sie nicht mit diesem Zeiger ändern werden.

Wenn Sie einen Zeiger haben wollen, der in dem Sinne konstant ist, dass er nicht auf etwas anderes zeigen kann, dann sollten Sie ihn so schreiben:

Bar * const obj = some_object;

Dies wird kompiliert und funktioniert einwandfrei:

const int p = 1, q = 2;
int r = 3;
const int* i = &p;
i = &q; // point it to a different const variable.
i = &r; // point it to a different non const variable.

0voto

Darren Punkte 662

Wie geschrieben, glaube ich, dass dies ein Zeiger auf ein const Bar-Objekt ist und kein konstanter Zeiger.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X