Angenommen, ich habe eine Klasse, die so aussieht (dies ist nur ein Beispiel):
class A {
double *ptr;
public:
A() : ptr( new double[100] ) {}
A( const A &other ) {
other.ptr[7] = 15;
}
void doNotChangeMyData() const {
ptr[43] = 14;
}
void changeMyData() {
ptr[43] = 14;
}
~A() { delete[] ptr; }
};
Die const
sowohl im Kopierkonstruktor als auch in der doNotChangeMyData
Funktion machen es so, dass ptr
es nicht geändert werden kann; Auf diese Weise kann ich jedoch weiterhin den Inhalt des Arrays ändern, auf das von verwiesen wird ptr
.
Gibt es eine Möglichkeit zu verhindern, dass der Inhalt des ptr
Arrays nur in const
Instanzen geändert wird , ohne "vorsichtig" zu sein (oder sich vom Rohzeiger zu entfernen)?
Ich weiß, ich könnte so etwas tun
void doNotChangeMyData() const {
const double *const ptr = this->ptr;
ptr[43] = 14; // then this would fail to compile
}
Aber ich möchte lieber nicht ...
std::vector
std::vector::operator[]()
kann Werte richtig ändern?vector
würde funktionieren.std::vector::operator[]() const
gibt eineconst
Referenz zurückAntworten:
Zeiger verbreiten sich nicht
const
. Das Hinzufügenconst
zum Typdouble*
ergibt Ausbeutendouble* const
, dieconst
bei Dereferenzierung zu einem Nichtwert führen.Stattdessen können Sie Folgendes verwenden
std::vector
:a
std::array
:oder ein eingebautes Array (nicht empfohlen):
Alle drei Optionen verbreiten sich
const
.Wenn Sie wirklich Zeiger verwenden möchten (dringend nicht empfohlen), verwenden Sie mindestens a
std::unique_ptr
, um eine manuelle Speicherverwaltung zu vermeiden. Sie können denstd::experimental::propagate_const
Wrapper aus den Grundlagen der Bibliothek verwenden. 2 TS:Es ist noch nicht im Standard, aber viele Compiler unterstützen es. Natürlich ist dieser Ansatz den richtigen Behältern unterlegen.
quelle
std::array
funktioniert nicht, wenn Sie die Größe beim Kompilieren nicht kennen.vector
fügt Overhead hinzu;unique_ptr
Fügt keinen Overhead hinzu, aber wenn der Zeiger gemeinsam genutzt werden muss, benötigen Sie einenshared_ptr
zusätzlichen Overhead. Ich glaube nicht, dass VS derzeit unterstütztpropagate_const
(zumindest die Header-Datei, auf die cppreference verweist, existiert nicht mit/std:c++latest
) :(vector
TBH wird häufig überschätzt, insbesondere im Vergleich zum Aufwand der manuellen Speicherverwaltung. Wenn Sie die Zeiger manuell freigeben, müssen Sie außerdem einen Referenzzähler verwenden, damit der Overhead nicht besonders istshared_ptr
. Ich wusste nicht, dass VS noch nicht unterstütztpropagate_const
(GCC und Clang unterstützen beide IIRC), aber es ist nicht schwer, unsere eigenen gemäß der Spezifikation einzuführen.vector
dann nehme seinen Inhalt über.data()
oder&vec[0]
und arbeite stattdessen direkt damit. Im Fall der Freigabe habe ich oft einen Besitzer des Zeigers, der erstellt und löscht, aber andere Klassen teilen die Daten.