QSharedDataPointer Class
template <typename T> class QSharedDataPointerDie Klasse QSharedDataPointer repräsentiert einen Zeiger auf ein implizit freigegebenes Objekt. Mehr...
Kopfzeile: | #include <QSharedDataPointer> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
qmake: | QT += core |
Hinweis: Alle Funktionen in dieser Klasse sind reentrant.
Ö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() |
T * | operator T *() |
const 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!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs) |
bool | operator!=(const T *ptr, const QSharedDataPointer<T> &rhs) |
bool | operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs) |
bool | operator==(const T *ptr, const QSharedDataPointer<T> &rhs) |
Detaillierte Beschreibung
QSharedDataPointer<T> macht das Schreiben eigener , implizit gemeinsam genutzter Klassen einfach. QSharedDataPointer implementiert Thread-sichere Referenzzählung und stellt sicher, dass das Hinzufügen von QSharedDataPointers zu Ihren reentranten Klassen diese nicht nicht-reentrant macht.
Implizites Sharing wird von vielen Qt-Klassen verwendet, um die Geschwindigkeit und Speichereffizienz von Zeigern mit der Benutzerfreundlichkeit von Klassen zu kombinieren. Siehe die Seite Shared Classes für weitere Informationen.
Angenommen, Sie möchten eine Employee
Klasse implizit gemeinsam nutzen. Die Prozedur ist:
- Definieren Sie die Klasse
Employee
so, dass sie ein einziges Datenelement vom TypQSharedDataPointer<EmployeeData>
enthält. - Definieren Sie die von QSharedData abgeleitete Klasse
EmployeeData
so, dass sie alle Datenelemente enthält, die Sie normalerweise in der KlasseEmployee
untergebracht hätten.
Um dies in der Praxis zu zeigen, betrachten wir den Quellcode der implizit gemeinsam genutzten Klasse Employee
. In der Header-Datei definieren wir die beiden Klassen Employee
und EmployeeData
.
#include <QSharedData> #include <QString> class EmployeeData : public QSharedData { public: EmployeeData() : id(-1) { } EmployeeData(const EmployeeData &other) : QSharedData(other), id(other.id), name(other.name) { } ~EmployeeData() { } 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) : d (other.d) { } 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 d-Zeiger vom Typ QSharedDataPointer<EmployeeData>
. Alle Zugriffe auf Mitarbeiterdaten müssen über den d-Zeiger von operator->()
erfolgen. Bei Schreibzugriffen ruft operator->()
automatisch detach() auf, das eine Kopie des gemeinsamen Datenobjekts erstellt, wenn die Referenzanzahl des gemeinsamen Datenobjekts größer als 1 ist. Dadurch wird sichergestellt, dass Schreibzugriffe auf ein Employee
Objekt keine anderen Employee
Objekte beeinflussen, die dasselbe EmployeeData
Objekt teilen.
Die Klasse EmployeeData
erbt QSharedData, die den Referenzzähler hinter den Kulissen bereitstellt. EmployeeData
hat einen Standardkonstruktor, einen Kopierkonstruktor und einen Destruktor. Normalerweise sind triviale Implementierungen dieser Funktionen 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 einfach. Beide erzeugen 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 nicht unbedingt erforderlich ist.
Employee(const Employee &other) : d (other.d) { }
Der Kopierkonstruktor ist hier nicht unbedingt erforderlich, da die Klasse EmployeeData
in derselben Datei wie die Klasse Employee
(employee.h
) enthalten ist. Es ist jedoch untypisch, die private Unterklasse von QSharedData in dieselbe Datei aufzunehmen wie die öffentliche Klasse, die den QSharedDataPointer enthält. Normalerweise ist die Idee, die private Unterklasse von QSharedData vor dem Benutzer zu verbergen, indem man sie in eine separate Datei aufnimmt, die nicht in die öffentliche Datei aufgenommen wird. In diesem Fall würden wir normalerweise die Klasse EmployeeData
in einer separaten Datei ablegen, die nicht in employee.h
enthalten ist. Stattdessen würden wir die private Unterklasse EmployeeData
einfach in employee.h
auf diese Weise vordeklarieren:
class EmployeeData;
Hätten wir es hier so gemacht, wäre der gezeigte Kopierkonstruktor erforderlich. Da der Kopierkonstruktor trivial ist, können Sie ihn auch einfach immer einbinden.
Hinter den Kulissen erhöht QSharedDataPointer automatisch die Referenzanzahl, wenn ein Employee
Objekt kopiert, zugewiesen oder als Parameter übergeben wird. Die Anzahl der Referenzen wird immer dann verringert, wenn ein Employee
Objekt gelöscht wird oder den Gültigkeitsbereich verlässt. Das freigegebene EmployeeData
Objekt wird automatisch gelöscht, wenn der Referenzzähler 0 erreicht.
In einer nicht-konstanten Mitgliedsfunktion von Employee
ruft QSharedDataPointer automatisch detach() auf, wenn der Zeiger d dereferenziert wird, um sicherzustellen, dass die Funktion mit 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() aufgrund mehrerer Dereferenzierungen des d-Zeigers mehr als einmal in einer Mitgliedsfunktion aufgerufen wird, detach(), wenn überhaupt, nur beim ersten Aufruf eine Kopie der gemeinsam genutzten Daten erstellt, da beim zweiten und den folgenden Aufrufen von detach() der Referenzzähler wieder 1 sein wird.
Beachten Sie jedoch, dass im zweiten Employee
-Konstruktor, der eine Mitarbeiter-ID und einen Namen annimmt, sowohl setId() als auch setName() aufgerufen werden, die jedoch keine Kopie beim Schreiben verursachen, da die Referenzanzahl für das neu konstruierte EmployeeData
-Objekt gerade auf 1 gesetzt wurde.
In den const-Mitgliedsfunktionen von Employee
führt die Dereferenzierung des Zeigers d nicht zum Aufruf von detach().
int id() const { return d->id; } QString name() const { return d->name; }
Beachten Sie, dass es nicht notwendig ist, einen Kopierkonstruktor oder einen Zuweisungsoperator für die Klasse Employee
zu implementieren, da der Kopierkonstruktor und der Zuweisungsoperator, die vom C++-Compiler bereitgestellt werden, die erforderlichen flachen Kopien Member für Member durchführen. Der einzige zu kopierende Member ist der Zeiger d, der ein QSharedDataPointer ist, dessen operator=()
lediglich die Referenzanzahl des gemeinsam genutzten EmployeeData
Objekts erhöht.
Implizites vs. explizites Sharing
Implizites Sharing ist für die Klasse Employee
möglicherweise nicht geeignet. Betrachten Sie ein einfaches Beispiel, das zwei Instanzen der implizit gemeinsam genutzten Klasse Employee
erzeugt.
#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 Durer, Mitarbeiter 1001. Beide Employee
Objekte zeigen auf dieselbe Instanz von EmployeeData
, die die Referenzanzahl 2 hat. Dann wird e1.setName("Hans Holbein")
aufgerufen, um den Namen des Angestellten zu ändern, aber da die Referenzanzahl größer als 1 ist, wird eine Kopie beim Schreiben durchgeführt, bevor der Name geändert wird. Nun verweisen e1
und e2
auf verschiedene EmployeeData
Objekte. Sie haben unterschiedliche Namen, aber beide haben die ID 1001, was wahrscheinlich nicht das ist, was Sie wollen. Sie können natürlich einfach mit e1.setId(1002)
weitermachen, wenn Sie wirklich einen zweiten, eindeutigen Angestellten schaffen wollen, aber wenn Sie nur den Namen des Angestellten überall ändern wollen, sollten Sie explicit sharing in der Klasse Employee
anstelle der impliziten Freigabe verwenden.
Wenn Sie den d-Zeiger in der Klasse Employee
als QExplicitlySharedDataPointer<EmployeeData>
deklarieren, wird die explizite Freigabe verwendet, und Kopiervorgänge bei Schreibvorgängen werden nicht automatisch ausgeführt (d. h. detach() wird nicht in Nicht-Konstanten-Funktionen aufgerufen). In diesem Fall wurde nach e1.setName("Hans Holbein")
der Name des Mitarbeiters geändert, aber sowohl e1 als auch e2 verweisen immer noch auf dieselbe Instanz von EmployeeData
, so dass es nur einen Mitarbeiter mit der ID 1001 gibt.
In der Dokumentation der Mitgliedsfunktionen bezieht sich d pointer immer auf den internen Zeiger auf das gemeinsame Datenobjekt.
Optimieren der Leistung für die Verwendung in Qt Containern
Sie sollten in Erwägung ziehen, Ihre implizit gemeinsam genutzte Klasse mit dem Q_DECLARE_TYPEINFO() Makro als beweglichen Typ zu markieren, wenn sie der obigen Klasse Employee
ähnelt und einen QSharedDataPointer oder QExplicitlySharedDataPointer als einziges Mitglied verwendet. Dies kann die Leistung und Speichereffizienz bei der Verwendung von Qt's Container-Klassen verbessern.
Siehe auch QSharedData, QExplicitlySharedDataPointer, QScopedPointer, und QSharedPointer.
Dokumentation der Membertypen
QSharedDataPointer::Type
Dies ist der Typ des gemeinsamen Datenobjekts. Der Zeiger d zeigt auf ein Objekt dieses Typs.
Dokumentation der Mitgliedsfunktionen
[noexcept]
QSharedDataPointer::QSharedDataPointer()
Konstruiert einen QSharedDataPointer, initialisiert mit nullptr
als d-Zeiger.
[explicit noexcept]
QSharedDataPointer::QSharedDataPointer(T *data)
Konstruiert einen QSharedDataPointer mit dem Zeiger d, der auf data gesetzt ist, und erhöht die Referenzanzahl von data.
[noexcept, since 6.0]
QSharedDataPointer::QSharedDataPointer(T *data, QAdoptSharedDataTag)
Konstruiert einen QSharedDataPointer mit dem Zeiger d, der auf data gesetzt ist. Der Referenzzähler von data wird nicht inkrementiert; dies kann verwendet werden, um Zeiger zu übernehmen, die von take() erhalten wurden.
Diese Funktion wurde in Qt 6.0 eingeführt.
Siehe auch take().
[noexcept]
QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T> &o)
Setzt den d-Zeiger von this auf den d-Zeiger in o und erhöht die Referenzanzahl des gemeinsamen Datenobjekts.
[noexcept]
QSharedDataPointer::QSharedDataPointer(QSharedDataPointer<T> &&o)
Move-konstruiert eine QSharedDataPointer-Instanz, die auf das gleiche Objekt zeigt, auf das o gezeigt hat.
QSharedDataPointer::~QSharedDataPointer()
Verringert die Referenzanzahl des gemeinsamen Datenobjekts. Wenn der Referenzzähler 0 wird, wird das gemeinsame Datenobjekt gelöscht. Anschließend wird es zerstört.
[protected]
T *QSharedDataPointer::clone()
Erstellt eine tiefe Kopie der aktuellen Daten und gibt sie 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 zur Verfügung gestellt, damit Sie "virtuelle Kopierkonstruktoren" für Ihre eigenen Typen unterstützen können. Um dies zu tun, sollten Sie eine Template-Spezialisierung dieser Funktion für Ihren eigenen Typ deklarieren, wie im folgenden Beispiel:
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 außer Kraft setzen und den richtigen polymorphen Typ zurückgeben.
[noexcept]
const T *QSharedDataPointer::constData() const
Gibt einen Konstantenzeiger auf das gemeinsame Datenobjekt zurück. Diese Funktion ruft nicht detach() auf.
Siehe auch data().
T *QSharedDataPointer::data()
Gibt einen Zeiger auf das gemeinsame Datenobjekt zurück. Diese Funktion ruft detach() auf.
Siehe auch constData().
[noexcept]
const T *QSharedDataPointer::data() const
Gibt einen Zeiger auf das gemeinsame Datenobjekt zurück. Diese Funktion ruft nicht detach() auf.
void QSharedDataPointer::detach()
Wenn die Referenzanzahl des gemeinsamen Datenobjekts größer als 1 ist, erstellt diese Funktion eine tiefe Kopie des gemeinsamen Datenobjekts und setzt den d-Zeiger dieses Objekts auf die Kopie.
Diese Funktion wird automatisch von nicht-konstanten Mitgliedsfunktionen von QSharedDataPointer aufgerufen, wenn eine Kopie beim Schreiben erforderlich ist. Sie brauchen sie nicht selbst aufzurufen.
[since 6.0]
T *QSharedDataPointer::get()
Dasselbe wie 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
Dasselbe wie 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 d-Zeiger von this auf ptr und erhöht den Referenzzähler von ptr, wenn ptr nicht nullptr
ist. Der Referenzzähler des alten gemeinsamen Datenobjekts wird dekrementiert, und das Objekt wird gelöscht, wenn der Referenzzähler 0 erreicht.
Diese Funktion wurde in Qt 6.0 eingeführt.
[noexcept]
void QSharedDataPointer::swap(QSharedDataPointer<T> &other)
Tauscht diesen gemeinsamen Datenzeiger mit other aus. Dieser Vorgang ist sehr schnell und schlägt nie fehl.
[noexcept, since 6.0]
T *QSharedDataPointer::take()
Gibt einen Zeiger auf das gemeinsam genutzte Objekt zurück und setzt dieses auf nullptr
zurück. (Das heißt, diese Funktion setzt den d-Zeiger von this auf nullptr
.)
Hinweis: Der Referenzzähler des zurückgegebenen Objekts wird nicht dekrementiert. Diese Funktion kann zusammen mit dem Konstruktor verwendet werden, der ein QAdoptSharedDataTag Tag-Objekt annimmt, um das gemeinsame Datenobjekt ohne zwischengeschaltete atomare Operationen zu übertragen.
Diese Funktion wurde in Qt 6.0 eingeführt.
T *QSharedDataPointer::operator T *()
Gibt einen Zeiger auf das gemeinsame Datenobjekt zurück. Diese Funktion ruft detach() auf.
Siehe auch data() und constData().
[noexcept]
const T *QSharedDataPointer::operator const T *() const
Gibt einen Zeiger auf das gemeinsame Datenobjekt zurück. Diese Funktion ruft nicht detach() auf.
[noexcept]
bool QSharedDataPointer::operator!() const
Gibt true
zurück, wenn der d-Zeiger von this nullptr
ist.
T &QSharedDataPointer::operator*()
Ermöglicht den Zugriff auf die Mitglieder des gemeinsamen Datenobjekts. Diese Funktion ruft detach() auf.
const T &QSharedDataPointer::operator*() const
Bietet konstanten Zugriff auf die Mitglieder des gemeinsamen Datenobjekts. Diese Funktion ruft nicht detach() auf.
T *QSharedDataPointer::operator->()
Ermöglicht den Zugriff auf die Mitglieder des gemeinsamen Datenobjekts. Diese Funktion ruft detach() auf.
[noexcept]
const T *QSharedDataPointer::operator->() const
Bietet konstanten Zugriff auf die Mitglieder des gemeinsamen Datenobjekts. Diese Funktion ruft nicht detach() auf.
[noexcept]
QSharedDataPointer<T> &QSharedDataPointer::operator=(QSharedDataPointer<T> &&other)
Verschieben - weist other dieser QSharedDataPointer Instanz zu.
[noexcept]
QSharedDataPointer<T> &QSharedDataPointer::operator=(T *o)
Setzt den d-Zeiger von this auf o und erhöht den Referenzzähler von o. Der Referenzzähler des alten gemeinsamen Datenobjekts von this wird dekrementiert. Wenn der Referenzzähler des alten gemeinsamen Datenobjekts 0 wird, wird das alte gemeinsame Datenobjekt gelöscht.
[noexcept]
QSharedDataPointer<T> &QSharedDataPointer::operator=(const QSharedDataPointer<T> &o)
Setzt den d-Zeiger von this auf den d-Zeiger von o und erhöht die Referenzanzahl des gemeinsamen Datenobjekts. Der Referenzzähler des alten gemeinsamen Datenobjekts von this wird dekrementiert. Wenn der Referenzzähler des alten gemeinsamen Datenobjekts 0 wird, wird das alte gemeinsame Datenobjekt gelöscht.
Verwandte Nicht-Mitglieder
[noexcept]
bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
Gibt true
zurück, wenn lhs und rhs nicht denselben d-Zeiger haben. Diese Funktion ruft nicht detach() auf.
[noexcept]
bool operator!=(const T *ptr, const QSharedDataPointer<T> &rhs)
Gibt true
zurück, wenn der d-Zeiger von rhs nicht ptr ist. d-Zeiger. Diese Funktion ruft nicht detach() auf.
[noexcept]
bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
Gibt true
zurück, wenn lhs und rhs denselben d-Zeiger haben. Diese Funktion ruft nicht detach() auf.
[noexcept]
bool operator==(const T *ptr, const QSharedDataPointer<T> &rhs)
Gibt true
zurück, wenn der d-Zeiger von rhs ptr ist. Diese Funktion ruft nicht detach() auf.
© 2025 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.