QSharedDataPointer Class
template <typename T> class QSharedDataPointerDie Klasse „QSharedDataPointer“ stellt einen Zeiger auf ein implizit gemeinsam genutztes Objekt dar. Mehr...
| Header: | #include <QSharedDataPointer> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
| Erbt von: | QSharedDataPointerBase |
Hinweis: Alle Funktionen dieser Klasse sind reentrant.
Vergleiche zu QSharedDataPointer
| Kategorie | Vergleichbare Typen |
|---|---|
| stark | QSharedDataPointer |
| strong | T* und std::nullptr_t. |
Öffentliche Typen
Öffentliche Funktionen
| QSharedDataPointer() | |
| QSharedDataPointer(T *data) | |
(since 6.0) | QSharedDataPointer(T *data, QAdoptSharedDataTag) |
| QSharedDataPointer(const QSharedDataPointer<T> &o) | |
| QSharedDataPointer(QSharedDataPointer<T> &&o) | |
| ~QSharedDataPointer() | |
| const T * | constData() const |
| T * | data() |
| const T * | data() const |
| void | detach() |
(since 6.0) T * | get() |
(since 6.0) const T * | get() const |
(since 6.0) void | reset(T *ptr = nullptr) |
| void | swap(QSharedDataPointer<T> &other) |
(since 6.0) T * | take() |
| operator T *() | |
| operator const T *() const | |
| bool | operator!() const |
| T & | operator*() |
| const T & | operator*() const |
| T * | operator->() |
| const T * | operator->() const |
| QSharedDataPointer<T> & | operator=(QSharedDataPointer<T> &&other) |
| QSharedDataPointer<T> & | operator=(T *o) |
| QSharedDataPointer<T> & | operator=(const QSharedDataPointer<T> &o) |
Geschützte Funktionen
| T * | clone() |
Verwandte Nicht-Mitglieder
| bool | operator!=(T *const &lhs, const QSharedDataPointer<T> &rhs) |
| bool | operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs) |
| bool | operator==(T *const &lhs, const QSharedDataPointer<T> &rhs) |
| bool | operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs) |
Ausführliche Beschreibung
`QSharedDataPointer` ist eine Template-Klasse, bei der der Template-Parameter ` T ` den Typ der gemeinsam genutzten Datenklasse angibt, die von ` QSharedData` abgeleitet ist.
QSharedDataPointer<T> erleichtert das Schreiben eigener implizit gemeinsam genutzter Klassen. QSharedDataPointer implementiert eine threadsichere Referenzzählung und stellt so sicher, dass das Hinzufügen von QSharedDataPointers zu Ihren reentranten Klassen diese nicht nicht-reentrant macht.
Die implizite Freigabe wird von vielen Qt-Klassen genutzt, um die Geschwindigkeit und Speichereffizienz von Zeigern mit der Benutzerfreundlichkeit von Klassen zu kombinieren. Weitere Informationen finden Sie auf der Seite „Shared Classes “.
Angenommen, Sie möchten eine „ Employee “-Klasse implizit gemeinsam genutzt machen. Die Vorgehensweise ist wie folgt:
- Definieren Sie die Klasse `
Employee` so, dass sie ein einziges Datenelement vom Typ `QSharedDataPointer<EmployeeData>` enthält. - Definieren Sie die Klasse „
EmployeeData“, die von „ QSharedData “ abgeleitet ist, so, dass sie alle Datenelemente enthält, die Sie normalerweise in die Klasse „Employee“ aufgenommen hätten.
Um dies in der Praxis zu veranschaulichen, sehen wir uns den Quellcode der implizit gemeinsam genutzten Klasse „ Employee “ an. In der Header-Datei definieren wir die beiden Klassen „ Employee “ und „ EmployeeData “.
#include <QSharedData>
#include <QSharedDataPointer>
#include <QString>
class EmployeeData : public QSharedData
{
public:
EmployeeData() : id(-1) {}
EmployeeData(const EmployeeData &other)
: QSharedData(other), id(other.id), name(other.name) {}
~EmployeeData() = default;
int id;
QString name;
};
class Employee
{
public:
Employee() { d = new EmployeeData; }
Employee(int id, const QString &name) {
d = new EmployeeData;
setId(id);
setName(name);
}
Employee(const Employee &other) = default;
Employee &operator=(const Employee &other) = default;
Employee(Employee &&other) = default;
Employee &operator=(Employee &&other) = default;
~Employee() = default;
void setId(int id) { d->id = id; }
void setName(const QString &name) { d->name = name; }
int id() const { return d->id; }
QString name() const { return d->name; }
private:
QSharedDataPointer<EmployeeData> d;
};Beachten Sie in der Klasse „ Employee “ das einzige Datenelement, einen Zeiger „d“ vom Typ „ QSharedDataPointer<EmployeeData> “. Alle Zugriffe auf Mitarbeiterdaten müssen über den Zeiger „d“ auf „ operator->() “ erfolgen. Bei Schreibzugriffen ruft „ operator->() “ automatisch „ detach()“ auf, wodurch eine Kopie des gemeinsam genutzten Datenobjekts erstellt wird, wenn dessen Referenzzähler größer als 1 ist. Dadurch wird sichergestellt, dass Schreibvorgänge an einem „ Employee “-Objekt keine Auswirkungen auf andere „ Employee “-Objekte haben, die dasselbe „ EmployeeData “-Objekt gemeinsam nutzen.
Die Klasse „ EmployeeData “ erbt von „ QSharedData “, das den Referenzzähler im Hintergrund bereitstellt. „ EmployeeData “ verfügt über einen Standardkonstruktor, einen Kopierkonstruktor und einen Destruktor. Normalerweise sind einfache Implementierungen dieser Konstruktoren alles, was in der Datenklasse für eine implizit gemeinsam genutzte Klasse benötigt wird.
Die Implementierung der beiden Konstruktoren für die Klasse ` Employee ` ist ebenfalls unkompliziert. Beide erstellen eine neue Instanz von ` EmployeeData ` und weisen sie dem Zeiger `d` zu.
Employee() { d = new EmployeeData; }
Employee(int id, const QString &name) {
d = new EmployeeData;
setId(id);
setName(name);
}Beachten Sie, dass die Klasse ` Employee ` auch einen trivialen Kopierkonstruktor definiert hat, der in diesem Fall streng genommen nicht erforderlich ist.
Employee(const Employee &other) = default;
Employee &operator=(const Employee &other) = default;
Employee(Employee &&other) = default;
Employee &operator=(Employee &&other) = default;
~Employee() = default;Der Kopierkonstruktor ist hier nicht zwingend erforderlich, da die Klasse „ EmployeeData “ in derselben Datei wie die Klasse „ Employee “ enthalten ist (employee.h). Es ist jedoch nicht üblich, die private Unterklasse von „ QSharedData “ in derselben Datei wie die öffentliche Klasse einzubinden, die den „QSharedDataPointer“ enthält. Normalerweise besteht der Ansatz darin, die private Unterklasse von QSharedData vor dem Benutzer zu verbergen, indem man sie in einer separaten Datei unterbringt, die nicht in die öffentliche Datei eingebunden wird. In diesem Fall würden wir die Klasse EmployeeData normalerweise in eine separate Datei auslagern, die nicht in employee.h eingebunden wird. Stattdessen würden wir die private Unterklasse EmployeeData in employee.h einfach auf folgende Weise vorerklären:
class EmployeeData;Hätten wir es hier so gemacht, wäre der gezeigte Kopierkonstruktor erforderlich. Da der Kopierkonstruktor trivial ist, kann man ihn genauso gut immer einfügen.
Hinter den Kulissen erhöht QSharedDataPointer automatisch die Referenzanzahl, sobald ein „ Employee “-Objekt kopiert, zugewiesen oder als Parameter übergeben wird. Es verringert die Referenzanzahl, sobald ein „ Employee “-Objekt gelöscht wird oder den Gültigkeitsbereich verlässt. Das gemeinsam genutzte „ EmployeeData “-Objekt wird automatisch gelöscht, sobald die Referenzanzahl 0 erreicht.
In einer nicht-konstanten Memberfunktion von ` Employee` ruft `QSharedDataPointer` automatisch ` detach()` auf, sobald der Zeiger `d` dereferenziert wird, um sicherzustellen, dass die Funktion auf ihrer eigenen Kopie der Daten arbeitet.
void setId(int id) { d->id = id; }
void setName(const QString &name) { d->name = name; }Beachten Sie, dass, wenn ` detach()` in einer Memberfunktion aufgrund mehrerer Dereferenzierungen des Zeigers `d` mehr als einmal aufgerufen wird, ` detach()` – wenn überhaupt – erst beim ersten Aufruf eine Kopie der gemeinsam genutzten Daten erstellt, da beim zweiten und allen folgenden Aufrufen von ` detach()` der Referenzzähler wieder 1 beträgt.
Beachten Sie jedoch, dass im zweiten Konstruktor von ` Employee `, der eine Mitarbeiter-ID und einen Namen entgegennimmt, sowohl `setId()` als auch `setName()` aufgerufen werden, diese jedoch kein „Copy-on-Write“ auslösen, da die Referenzanzahl für das neu erstellte ` EmployeeData `-Objekt gerade auf 1 gesetzt wurde.
In den const-Mitgliedsfunktionen von Employee führt die Dereferenzierung des Zeigers d nicht dazu, dass detach() aufgerufen wird.
int id() const { return d->id; }
QString name() const { return d->name; }Beachten Sie, dass für die Klasse ` Employee ` kein Kopierkonstruktor und kein Zuweisungsoperator implementiert werden müssen, da der vom C++-Compiler bereitgestellte Kopierkonstruktor und Zuweisungsoperator die erforderliche flache Kopie von Mitglied zu Mitglied durchführen. Das einzige zu kopierende Mitglied ist der Zeiger `d`, bei dem es sich um einen `QSharedDataPointer` handelt, dessen ` operator=() ` lediglich die Referenzanzahl des gemeinsam genutzten Objekts ` EmployeeData ` erhöht.
Implizites vs. explizites Teilen
Implizites Sharing ist für die Klasse „ Employee “ möglicherweise nicht geeignet. Betrachten wir ein einfaches Beispiel, in dem zwei Instanzen der implizit gemeinsam genutzten Klasse „ Employee “ erstellt werden.
#include "employee.h"
int main()
{
Employee e1(1001, "Albrecht Durer");
Employee e2 = e1;
e1.setName("Hans Holbein");
}Nachdem der zweite Mitarbeiter „e2“ erstellt und ihm „e1“ zugewiesen wurde, verweisen sowohl „ e1 “ als auch „ e2 “ auf Albrecht Dürer, Mitarbeiter 1001. Beide „ Employee “-Objekte verweisen auf dieselbe Instanz von „ EmployeeData “, deren Referenzzähler den Wert 2 hat. Anschließend wird e1.setName("Hans Holbein") aufgerufen, um den Namen des Mitarbeiters zu ändern. Da die Referenzanzahl jedoch größer als 1 ist, wird vor der Namensänderung ein „Copy-on-Write“ durchgeführt. Nun verweisen e1 und e2 auf unterschiedliche EmployeeData -Objekte. Sie haben unterschiedliche Namen, aber beide die ID 1001, was wahrscheinlich nicht Ihrem Wunsch entspricht. Sie können natürlich einfach mit ` e1.setId(1002)` fortfahren, wenn Sie wirklich einen zweiten, eindeutigen Mitarbeiter anlegen möchten. Wenn Sie jedoch lediglich den Namen des Mitarbeiters überall ändern wollen, sollten Sie in der Klasse ` Employee ` die Verwendung von ` explicit sharing ` anstelle der impliziten gemeinsamen Nutzung in Betracht ziehen.
Wenn Sie den Zeiger `d` in der Klasse ` Employee ` als ` QExplicitlySharedDataPointer<EmployeeData>` deklarieren, wird explizites Sharing verwendet und „Copy-on-Write“-Operationen werden nicht automatisch durchgeführt (d. h., ` detach()` wird in Nicht-const-Funktionen nicht aufgerufen). In diesem Fall hat sich nach dem Aufruf von ` e1.setName("Hans Holbein")` der Name des Mitarbeiters geändert, aber sowohl `e1` als auch `e2` verweisen weiterhin auf dieselbe Instanz von ` EmployeeData`, sodass es nur einen Mitarbeiter mit der ID 1001 gibt.
In der Dokumentation zu Mitgliedsfunktionen verweist der Zeiger `d` immer auf den internen Zeiger auf das gemeinsam genutzte Datenobjekt.
Leistungsoptimierung für die Verwendung in Qt-Containern
Sie sollten in Erwägung ziehen, Ihre implizit gemeinsam genutzte Klasse mithilfe des Makros ` Q_DECLARE_TYPEINFO()` als verschiebbaren Typ zu kennzeichnen, wenn sie der oben genannten Klasse ` Employee ` ähnelt und einen `QSharedDataPointer` oder einen ` QExplicitlySharedDataPointer ` als einziges Mitglied verwendet. Dies kann die Leistung und die Speichereffizienz bei der Verwendung von Qt-Containerklassen verbessern.
Siehe auch „ QSharedData“ , „ QExplicitlySharedDataPointer “, „ QScopedPointer “ und „ QSharedPointer “.
Dokumentation zu Mitgliedstypen
QSharedDataPointer::Type
Dies ist der Typ des gemeinsam genutzten Datenobjekts. Der Zeiger `d` verweist auf ein Objekt dieses Typs.
Dokumentation der Mitgliedsfunktionen
[noexcept] QSharedDataPointer::QSharedDataPointer()
Erstellt einen `QSharedDataPointer`, der mit ` nullptr ` als Zeiger `d` initialisiert ist.
[explicit noexcept] QSharedDataPointer::QSharedDataPointer(T *data)
Erstellt einen `QSharedDataPointer`, bei dem der Zeiger `d` auf ` data ` gesetzt ist, und erhöht die Referenzanzahl von ` data`.
[noexcept, since 6.0] QSharedDataPointer::QSharedDataPointer(T *data, QAdoptSharedDataTag)
Erstellt einen `QSharedDataPointer`, wobei der Zeiger `d` auf ` data` gesetzt wird. Der Referenzzähler von ` data` wird nicht erhöht; dies kann genutzt werden, um Zeiger zu übernehmen, die über ` take()` erhalten wurden.
Diese Funktion wurde in Qt 6.0 eingeführt.
Siehe auch ` take()`.
[noexcept] QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T> &o)
Setzt den Zeiger „d“ dieses Objekts auf den Zeiger „d“ in „ o “ und erhöht die Referenzanzahl des gemeinsam genutzten Datenobjekts.
[noexcept] QSharedDataPointer::QSharedDataPointer(QSharedDataPointer<T> &&o)
Erstellt eine QSharedDataPointer-Instanz und sorgt dafür, dass diese auf dasselbe Objekt verweist, auf das zuvor o verwiesen hat.
QSharedDataPointer::~QSharedDataPointer()
Verringert die Referenzanzahl des gemeinsam genutzten Datenobjekts. Wenn die Referenzanzahl 0 wird, wird das gemeinsam genutzte Datenobjekt gelöscht. Es wird daraufhin zerstört.
[protected] T *QSharedDataPointer::clone()
Erstellt eine tiefe Kopie der aktuellen Daten und gibt diese zurück. Diese Funktion wird von ` detach()` aufgerufen, wenn die Referenzanzahl größer als 1 ist, um die neue Kopie zu erstellen. Diese Funktion verwendet den Operator `new` und ruft den Kopierkonstruktor des Typs ` T` auf.
Diese Funktion wird bereitgestellt, damit Sie „virtuelle Kopierkonstruktoren“ für Ihre eigenen Typen unterstützen können. Dazu sollten Sie eine Template-Spezialisierung dieser Funktion für Ihren eigenen Typ deklarieren, wie im folgenden Beispiel gezeigt:
template<>
EmployeeData *QSharedDataPointer<EmployeeData>::clone()
{
return d->clone();
}Im obigen Beispiel ruft die Template-Spezialisierung für die Funktion `clone()` die virtuelle Funktion `EmployeeData::clone() ` auf. Eine von `EmployeeData` abgeleitete Klasse könnte diese Funktion überschreiben und den entsprechenden polymorphen Typ zurückgeben.
[noexcept] const T *QSharedDataPointer::constData() const
Gibt einen const-Zeiger auf das gemeinsam genutzte Datenobjekt zurück. Diese Funktion ruft detach() nicht auf.
Siehe auch ` data()`.
T *QSharedDataPointer::data()
Gibt einen Zeiger auf das gemeinsam genutzte Datenobjekt zurück. Diese Funktion ruft „ detach()“ auf.
Siehe auch ` constData()`.
[noexcept] const T *QSharedDataPointer::data() const
Gibt einen Zeiger auf das gemeinsam genutzte Datenobjekt zurück. Diese Funktion ruft „ detach()“ nicht auf.
void QSharedDataPointer::detach()
Wenn die Referenzanzahl des gemeinsam genutzten Datenobjekts größer als 1 ist, erstellt diese Funktion eine tiefe Kopie des gemeinsam genutzten Datenobjekts und setzt den Zeiger `d` dieses Objekts auf die Kopie.
Diese Funktion wird automatisch von nicht-konstanten Member-Funktionen von ` QSharedDataPointer ` aufgerufen, wenn „Copy-on-Write“ erforderlich ist. Sie müssen sie nicht selbst aufrufen.
[since 6.0] T *QSharedDataPointer::get()
Entspricht „ data()“. Diese Funktion wird aus Gründen der STL-Kompatibilität bereitgestellt.
Diese Funktion wurde in Qt 6.0 eingeführt.
[noexcept, since 6.0] const T *QSharedDataPointer::get() const
Entspricht „ data()“. Diese Funktion wird aus Gründen der STL-Kompatibilität bereitgestellt.
Diese Funktion wurde in Qt 6.0 eingeführt.
[noexcept, since 6.0] void QSharedDataPointer::reset(T *ptr = nullptr)
Setzt den Zeiger „d“ dieses Objekts auf „ ptr “ und erhöht die Referenzanzahl von „ ptr “, sofern „ ptr “ nicht „ nullptr “ ist. Die Referenzanzahl des alten gemeinsam genutzten Datenobjekts wird verringert, und das Objekt wird gelöscht, sobald die Referenzanzahl 0 erreicht.
Diese Funktion wurde in Qt 6.0 eingeführt.
[noexcept] void QSharedDataPointer::swap(QSharedDataPointer<T> &other)
Tauscht diesen Zeiger auf gemeinsam genutzte Daten mit other aus. Dieser Vorgang ist sehr schnell und schlägt niemals fehl.
[noexcept, since 6.0] T *QSharedDataPointer::take()
Gibt einen Zeiger auf das gemeinsam genutzte Objekt zurück und setzt diesen auf „ nullptr “ zurück. (Das heißt, diese Funktion setzt den Zeiger „d“ von „this“ auf „ nullptr “.)
Hinweis: Die Referenzanzahl des zurückgegebenen Objekts wird nicht verringert. Diese Funktion kann zusammen mit dem Konstruktor verwendet werden, der ein ` QAdoptSharedDataTag `-Tag-Objekt entgegennimmt, um das gemeinsam genutzte Datenobjekt ohne dazwischenliegende atomare Operationen zu übertragen.
Diese Funktion wurde in Qt 6.0 eingeführt.
QSharedDataPointer::operator T *()
Gibt einen Zeiger auf das gemeinsam genutzte Datenobjekt zurück. Diese Funktion ruft „ detach()“ auf.
Siehe auch „ data()“ und „ constData()“.
[noexcept] QSharedDataPointer::operator const T *() const
Gibt einen Zeiger auf das gemeinsam genutzte Datenobjekt zurück. Diese Funktion ruft „ detach()“ nicht auf.
[noexcept] bool QSharedDataPointer::operator!() const
Gibt „ true “ zurück, wenn der Zeiger „d“ von „this“ auf „ nullptr “ verweist.
T &QSharedDataPointer::operator*()
Bietet Zugriff auf die Elemente des gemeinsam genutzten Datenobjekts. Diese Funktion ruft die Funktion „ detach()“ auf.
const T &QSharedDataPointer::operator*() const
Bietet const-Zugriff auf die Elemente des gemeinsam genutzten Datenobjekts. Diese Funktion ruft „ detach()“ nicht auf.
T *QSharedDataPointer::operator->()
Bietet Zugriff auf die Elemente des gemeinsam genutzten Datenobjekts. Diese Funktion ruft die Funktion „ detach()“ auf.
[noexcept] const T *QSharedDataPointer::operator->() const
Bietet „const“-Zugriff auf die Elemente des gemeinsam genutzten Datenobjekts. Diese Funktion ruft „ detach()“ nicht auf.
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(QSharedDataPointer<T> &&other)
Weist „ other “ dieser „ QSharedDataPointer “-Instanz zu.
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(T *o)
Setzt den Zeiger „d“ von „this“ auf „ o “ und erhöht die Referenzanzahl von „ o “. Die Referenzanzahl des alten gemeinsam genutzten Datenobjekts von „this“ wird verringert. Wenn die Referenzanzahl des alten gemeinsam genutzten Datenobjekts den Wert 0 erreicht, wird das alte gemeinsam genutzte Datenobjekt gelöscht.
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(const QSharedDataPointer<T> &o)
Setzt den Zeiger „d“ dieses Objekts auf den Zeiger „d“ von o und erhöht die Referenzanzahl des gemeinsam genutzten Datenobjekts. Die Referenzanzahl des alten gemeinsam genutzten Datenobjekts dieses Objekts wird verringert. Wenn die Referenzanzahl des alten gemeinsam genutzten Datenobjekts den Wert 0 erreicht, wird das alte gemeinsam genutzte Datenobjekt gelöscht.
Verwandte Nicht-Mitglieder
[noexcept] bool operator!=(T *const &lhs, const QSharedDataPointer<T> &rhs)
Gibt „ true “ zurück, wenn der Zeiger „d“ von „ rhs “ nicht „ lhs “ ist. Zeiger „d“. Diese Funktion ruft „ detach()“ nicht auf.
[noexcept] bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
Gibt „ true “ zurück, wenn „ lhs “ und „ rhs “ nicht denselben Zeiger „d“ haben. Diese Funktion ruft „ detach()“ nicht auf.
[noexcept] bool operator==(T *const &lhs, const QSharedDataPointer<T> &rhs)
Gibt „ true “ zurück, wenn der Zeiger „d“ von „ rhs “ auf „ lhs “ verweist. Diese Funktion ruft „ detach()“ nicht auf.
[noexcept] bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
Gibt „ true “ zurück, wenn „ lhs “ und „ rhs “ denselben Zeiger „d“ haben. Diese Funktion ruft „ detach()“ nicht auf.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.