Sur cette page

QSharedDataPointer Class

template <typename T> class QSharedDataPointer

La classe QSharedDataPointer représente un pointeur sur un objet implicitement partagé. Plus d'informations...

En-tête : #include <QSharedDataPointer>
CMake : find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake : QT += core
Hérite : QSharedDataPointerBase

Cette classe est fortement comparable.

Cette classe est fortement comparable à T* et std::nullptr_t.

Remarque : Toutes les fonctions de cette classe sont réentrantes.

Types publics

Fonctions publiques

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)

Fonctions protégées

T *clone()
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)

Description détaillée

QSharedDataPointer<T> facilite l'écriture de vos propres classes implicitement partagées. QSharedDataPointer implémente un comptage de références à l'abri des threads, ce qui garantit que l'ajout de QSharedDataPointers à vos classes réentrantes ne les rendra pas non réentrantes.

Lepartage implicite est utilisé par de nombreuses classes Qt pour combiner la vitesse et l'efficacité mémoire des pointeurs avec la facilité d'utilisation des classes. Voir la page sur les classes partagées pour plus d'informations.

Supposons que vous souhaitiez rendre une classe Employee implicitement partagée. La procédure est la suivante :

  • Définissez la classe Employee comme ayant un seul membre de données de type QSharedDataPointer<EmployeeData>.
  • Définissez la classe EmployeeData dérivée de QSharedData pour qu'elle contienne tous les membres de données que vous auriez normalement placés dans la classe Employee.

Pour montrer cela en pratique, nous examinons le code source de la classe Employee implicitement partagée. Dans le fichier d'en-tête, nous définissons les deux classes Employee et 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;
};

Dans la classe Employee, notez l'unique membre de données, un pointeur d de type QSharedDataPointer<EmployeeData>. Tous les accès aux données de l'employé doivent passer par le pointeur d de la classe operator->(). Pour les accès en écriture, operator->() appellera automatiquement detach(), qui crée une copie de l'objet de données partagées si le nombre de références de l'objet de données partagées est supérieur à 1. Cela garantit que les écritures dans un objet Employee n'affectent pas les autres objets Employee qui partagent le même objet EmployeeData.

La classe EmployeeData hérite de QSharedData, qui fournit le compteur de références en coulisse. EmployeeData possède un constructeur par défaut, un constructeur de copie et un destructeur. Normalement, des implémentations triviales de ces éléments sont tout ce qui est nécessaire dans la classe de données pour une classe implicitement partagée.

L'implémentation des deux constructeurs de la classe Employee est également simple. Tous deux créent une nouvelle instance de EmployeeData et l'affectent au pointeur d.

Employee() { d = new EmployeeData; }

Employee(int id, const QString &name) {
    d = new EmployeeData;
    setId(id);
    setName(name);
}

Notez que la classe Employee possède également un constructeur de copie trivial, qui n'est pas strictement nécessaire dans ce cas.

Employee(const Employee &other) = default;
Employee &operator=(const Employee &other) = default;

Employee(Employee &&other) = default;
Employee &operator=(Employee &&other) = default;

~Employee() = default;

Le constructeur de copie n'est pas strictement nécessaire ici, car la classe EmployeeData est incluse dans le même fichier que la classe Employee (employee.h). Cependant, inclure la sous-classe privée de QSharedData dans le même fichier que la classe publique contenant le QSharedDataPointer n'est pas typique. Normalement, l'idée est de cacher la sous-classe privée de QSharedData à l'utilisateur en la plaçant dans un fichier séparé qui ne serait pas inclus dans le fichier public. Dans ce cas, nous devrions normalement placer la classe EmployeeData dans un fichier séparé, qui ne serait pas inclus dans employee.h. Au lieu de cela, nous devrions simplement prédéclarer la sous-classe privée EmployeeData dans employee.h de cette façon :

class EmployeeData;

Si nous avions procédé de cette manière ici, le constructeur de copie illustré serait nécessaire. Étant donné que le constructeur de copie est trivial, il est préférable de l'inclure systématiquement.

En coulisses, QSharedDataPointer incrémente automatiquement le nombre de références chaque fois qu'un objet Employee est copié, assigné ou passé en paramètre. Il décrémente le nombre de références chaque fois qu'un objet Employee est supprimé ou sort du champ d'application. L'objet EmployeeData partagé est supprimé automatiquement lorsque le nombre de références atteint 0.

Dans une fonction membre non-const de Employee, chaque fois que le pointeur d est déréférencé, QSharedDataPointer appelle automatiquement detach() pour s'assurer que la fonction opère sur sa propre copie des données.

void setId(int id) { d->id = id; }

void setName(const QString &name) { d->name = name; }

Notez que si detach() est appelé plusieurs fois dans une fonction membre en raison de déréférencements multiples du pointeur d, detach() ne créera une copie des données partagées que la première fois qu'il est appelé, voire pas du tout, car lors du deuxième appel et des appels suivants de detach(), le nombre de références sera à nouveau de 1.

Mais notez que dans le deuxième constructeur de Employee, qui prend un numéro d'employé et un nom, setId() et setName() sont tous deux appelés, mais ils ne provoquent pas de copie en écriture, parce que le nombre de références pour l'objet EmployeeData nouvellement construit vient juste d'être fixé à 1.

Dans les fonctions membres constantes de Employee, le déréférencement du pointeur d n ' entraîne pas l'appel de detach().

int id() const { return d->id; }

QString name() const { return d->name; }

Notez qu'il n'est pas nécessaire d'implémenter un constructeur de copie ou un opérateur d'affectation pour la classe Employee, car le constructeur de copie et l'opérateur d'affectation fournis par le compilateur C++ effectueront la copie superficielle membre par membre requise. Le seul membre à copier est le pointeur d, qui est un QSharedDataPointer, dont operator=() incrémente simplement le nombre de références de l'objet partagé EmployeeData.

Partage implicite ou explicite

Le partage implicite peut ne pas convenir à la classe Employee. Prenons un exemple simple qui crée deux instances de la classe Employee partagée implicitement.

#include "employee.h"

int main()
{
    Employee e1(1001, "Albrecht Durer");
    Employee e2 = e1;
    e1.setName("Hans Holbein");
}

Une fois que le deuxième employé e2 a été créé et que e1 lui a été attribué, les objets e1 et e2 font tous deux référence à Albrecht Durer, employé 1001. Les deux objets Employee pointent vers la même instance de EmployeeData, qui a un nombre de références de 2. Ensuite, e1.setName("Hans Holbein") est appelé pour modifier le nom de l'employé, mais comme le nombre de références est supérieur à 1, une copie en écriture est effectuée avant que le nom ne soit modifié. À présent, e1 et e2 pointent vers différents objets EmployeeData. Ils ont des noms différents, mais tous deux ont l'ID 1001, ce qui n'est probablement pas ce que vous voulez. Vous pouvez, bien sûr, continuer avec e1.setId(1002), si vous voulez vraiment créer un deuxième employé unique, mais si vous voulez seulement changer le nom de l'employé partout, envisagez d'utiliser explicit sharing dans la classe Employee au lieu du partage implicite.

Si vous déclarez que le pointeur d de la classe Employee est QExplicitlySharedDataPointer<EmployeeData>, alors le partage explicite est utilisé et les opérations de copie et d'écriture ne sont pas effectuées automatiquement (c'est-à-dire que detach() n'est pas appelé dans les fonctions non constantes). Dans ce cas, après e1.setName("Hans Holbein"), le nom de l'employé a été modifié, mais e1 et e2 font toujours référence à la même instance de EmployeeData, de sorte qu'il n'y a qu'un seul employé avec l'ID 1001.

Dans la documentation des fonctions membres, d pointer fait toujours référence au pointeur interne de l'objet de données partagées.

Optimiser les performances pour l'utilisation dans les conteneurs Qt

Vous devriez envisager de marquer votre classe implicitement partagée comme un type mobile en utilisant la macro Q_DECLARE_TYPEINFO() si elle ressemble à la classe Employee ci-dessus et utilise un QSharedDataPointer ou QExplicitlySharedDataPointer comme seul membre. Cela peut améliorer les performances et l'efficacité de la mémoire lors de l'utilisation des classes conteneurs de Qt.

Voir aussi QSharedData, QExplicitlySharedDataPointer, QScopedPointer, et QSharedPointer.

Documentation sur les types de membres

QSharedDataPointer::Type

Il s'agit du type d'objet de données partagées. Le pointeur d pointe sur un objet de ce type.

Documentation des fonctions membres

[noexcept] QSharedDataPointer::QSharedDataPointer()

Construit un QSharedDataPointer initialisé avec nullptr comme pointeur d.

[explicit noexcept] QSharedDataPointer::QSharedDataPointer(T *data)

Construit un QSharedDataPointer avec un pointeur d défini sur data et incrémente le nombre de références de data.

[noexcept, since 6.0] QSharedDataPointer::QSharedDataPointer(T *data, QAdoptSharedDataTag)

Construit un QSharedDataPointer avec d pointeur fixé à data. Le compteur de référence de datan' est pas incrémenté ; cela peut être utilisé pour adopter des pointeurs obtenus à partir de take().

Cette fonction a été introduite dans Qt 6.0.

Voir aussi take().

[noexcept] QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T> &o)

Fixe le pointeur d de this au pointeur d de o et incrémente le nombre de références de l'objet de données partagées.

[noexcept] QSharedDataPointer::QSharedDataPointer(QSharedDataPointer<T> &&o)

Move-construit une instance de QSharedDataPointer, en la faisant pointer sur le même objet que o.

QSharedDataPointer::~QSharedDataPointer()

Diminue le nombre de références de l'objet de données partagées. Si le nombre de références devient 0, l'objet de données partagées est supprimé. Celui-ci est alors détruit.

[protected] T *QSharedDataPointer::clone()

Crée et renvoie une copie profonde des données actuelles. Cette fonction est appelée par detach() lorsque le nombre de références est supérieur à 1 afin de créer la nouvelle copie. Cette fonction utilise l'opérateur new et appelle le constructeur de copie du type T.

Cette fonction est fournie pour que vous puissiez prendre en charge les "constructeurs de copie virtuels" pour vos propres types. Pour ce faire, vous devez déclarer une spécialisation de modèle de cette fonction pour votre propre type, comme dans l'exemple ci-dessous :

template<>
EmployeeData *QSharedDataPointer<EmployeeData>::clone()
{
    return d->clone();
}

Dans l'exemple ci-dessus, la spécialisation du modèle pour la fonction clone() appelle la fonction virtuelle EmployeeData::clone(). Une classe dérivée de EmployeeData pourrait surcharger cette fonction et renvoyer le type polymorphe approprié.

[noexcept] const T *QSharedDataPointer::constData() const

Renvoie un pointeur constant vers l'objet de données partagées. Cette fonction n' appelle pas detach().

Voir aussi data().

T *QSharedDataPointer::data()

Renvoie un pointeur sur l'objet de données partagées. Cette fonction appelle detach().

Voir aussi constData().

[noexcept] const T *QSharedDataPointer::data() const

Renvoie un pointeur sur l'objet de données partagées. Cette fonction n' appelle pas detach().

void QSharedDataPointer::detach()

Si le nombre de références de l'objet de données partagées est supérieur à 1, cette fonction crée une copie profonde de l'objet de données partagées et place le pointeur d de cet objet sur la copie.

Cette fonction est appelée automatiquement par les fonctions membres non-const de QSharedDataPointer si une copie en écriture est nécessaire. Vous n'avez pas besoin de l'appeler vous-même.

[since 6.0] T *QSharedDataPointer::get()

Identique à data(). Cette fonction est fournie pour la compatibilité STL.

Cette fonction a été introduite dans Qt 6.0.

[noexcept, since 6.0] const T *QSharedDataPointer::get() const

Identique à data(). Cette fonction est fournie pour la compatibilité STL.

Cette fonction a été introduite dans Qt 6.0.

[noexcept, since 6.0] void QSharedDataPointer::reset(T *ptr = nullptr)

Définit le pointeur d de this à ptr et incrémente le nombre de références de ptr si ptr n'est pas nullptr. Le nombre de références de l'ancien objet de données partagées est décrémenté et l'objet est supprimé si le nombre de références atteint 0.

Cette fonction a été introduite dans Qt 6.0.

[noexcept] void QSharedDataPointer::swap(QSharedDataPointer<T> &other)

Échange ce pointeur de données partagées avec other. Cette opération est très rapide et n'échoue jamais.

[noexcept, since 6.0] T *QSharedDataPointer::take()

Renvoie un pointeur sur l'objet partagé et réinitialise ce dernier à nullptr(c'est-à-dire que cette fonction définit le pointeur d de cet objet à nullptr).

Remarque : le nombre de références de l'objet retourné ne sera pas décrémenté. Cette fonction peut être utilisée avec le constructeur qui prend un objet de balise QAdoptSharedDataTag pour transférer l'objet de données partagées sans opérations atomiques intermédiaires.

Cette fonction a été introduite dans Qt 6.0.

QSharedDataPointer::operator T *()

Renvoie un pointeur sur l'objet de données partagées. Cette fonction appelle detach().

Voir aussi data() et constData().

[noexcept] QSharedDataPointer::operator const T *() const

Renvoie un pointeur sur l'objet de données partagées. Cette fonction n' appelle pas detach().

[noexcept] bool QSharedDataPointer::operator!() const

Renvoie true si le pointeur d de this est nullptr.

T &QSharedDataPointer::operator*()

Permet d'accéder aux membres de l'objet de données partagées. Cette fonction appelle detach().

const T &QSharedDataPointer::operator*() const

Fournit un accès constant aux membres de l'objet de données partagées. Cette fonction n' appelle pas detach().

T *QSharedDataPointer::operator->()

Permet d'accéder aux membres de l'objet de données partagées. Cette fonction appelle detach().

[noexcept] const T *QSharedDataPointer::operator->() const

Fournit un accès constant aux membres de l'objet de données partagées. Cette fonction n' appelle pas detach().

[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(QSharedDataPointer<T> &&other)

Move-assigne other à cette instance QSharedDataPointer.

[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(T *o)

Définit le pointeur d de cet objet à o et incrémente le nombre de références de o. Le nombre de références de l'ancien objet de données partagées de this est décrémenté. Si le nombre de références de l'ancien objet de données partagées devient 0, l'ancien objet de données partagées est supprimé.

[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(const QSharedDataPointer<T> &o)

Définit le pointeur d de this au pointeur d de o et incrémente le nombre de références de l'objet de données partagées. Le nombre de références de l'ancien objet de données partagées de this est décrémenté. Si le nombre de références de l'ancien objet de données partagées devient 0, l'ancien objet de données partagées est supprimé.

Non-membres apparentés

[noexcept] bool operator!=(T *const &lhs, const QSharedDataPointer<T> &rhs)

Renvoie true si le pointeur d de rhs n' est pas lhs. pointeur d. Cette fonction n' appelle pas detach().

[noexcept] bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)

Renvoie true si lhs et rhs n'ont pas le même pointeur d. Cette fonction n' appelle pas detach().

[noexcept] bool operator==(T *const &lhs, const QSharedDataPointer<T> &rhs)

Renvoie true si le pointeur d de rhs est lhs. Cette fonction n' appelle pas detach().

[noexcept] bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)

Renvoie true si lhs et rhs ont le même pointeur d. Cette fonction n' appelle pas detach().

© 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.