Sur cette page

QSharedDataPointer Class

template <typename T> class QSharedDataPointer

La classe `QSharedDataPointer` représente un pointeur vers un objet implicitement partagé. En savoir plus...

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

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

Comparaisons de QSharedDataPointer

CatégorieTypes comparables
strongQSharedDataPointer
strongT* et std::nullptr_t.

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 est une classe de modèle dont le paramètre de modèle T spécifie le type de la classe de données partagées dérivée de QSharedData.

QSharedDataPointer<T> facilite la création de vos propres classes à partage implicite. QSharedDataPointer implémente un comptage de références sûr pour les threads, garantissant ainsi que l’ajout de QSharedDataPointers à vos classes réentrantes ne les rendra pas non réentrantes.

Le partage implicite est utilisé par de nombreuses classes Qt afin d’allier la rapidité et l’efficacité mémoire des pointeurs à la facilité d’utilisation des classes. Consultez la page 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 ` de manière à ce qu’elle comporte un seul membre de données de type ` QSharedDataPointer<EmployeeData>`.
  • Définissez la classe ` EmployeeData ` comme dérivée de ` QSharedData ` afin qu’elle contienne tous les membres de données que vous auriez normalement placés dans la classe ` Employee `.

Pour illustrer cela concrètement, nous examinons le code source de la classe Employee, qui est 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 le membre de données unique, un pointeur `d` de type ` QSharedDataPointer<EmployeeData>`. Tous les accès aux données de l’employé doivent passer par la classe ` operator->()` associée au pointeur `d`. Pour les accès en écriture, ` operator->() ` appellera automatiquement ` detach()`, qui crée une copie de l’objet de données partagé si le compteur de références de cet objet est supérieur à 1. Cela garantit que les écritures sur un objet Employee n’affectent aucun autre objet Employee partageant le même objet EmployeeData.

La classe EmployeeData hérite de QSharedData, qui fournit le compteur de références en arrière-plan. EmployeeData dispose d’un constructeur par défaut, d’un constructeur de copie et d’un destructeur. En règle générale, des implémentations triviales de ces éléments suffisent dans la classe de données pour une classe implicitement partagée.

L’implémentation des deux constructeurs pour la classe ` Employee ` est également simple. Tous deux créent une nouvelle instance de ` EmployeeData ` et l’attribuent 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 dispose également d’un constructeur de copie trivial, ce 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 une pratique courante. Normalement, l’idée est de masquer 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, on placerait normalement la classe EmployeeData dans un fichier séparé, qui ne serait pas inclus dans employee.h. À la place, on se contenterait de prédéclarer la sous-classe privée EmployeeData dans employee.h de la manière suivante :

class EmployeeData;

Si nous avions procédé ainsi ici, le constructeur de copie présenté serait obligatoire. Comme ce constructeur de copie est trivial, autant l’inclure systématiquement.

En arrière-plan, `QSharedDataPointer` incrémente automatiquement le compteur de références chaque fois qu’un objet ` Employee ` est copié, assigné ou passé en paramètre. Il décrémente le compteur de références chaque fois qu’un objet ` Employee ` est supprimé ou sort de sa portée. L’objet partagé ` EmployeeData ` est supprimé automatiquement dès que le compteur de références atteint 0.

Dans une fonction membre non constante 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ée plusieurs fois dans une fonction membre en raison de multiples déréférencements du pointeur d, detach() ne créera une copie des données partagées que lors de son premier appel (le cas échéant), car lors du deuxième appel et des appels suivants de detach(), le compteur de références sera à nouveau égal à 1.

Mais notez que dans le deuxième constructeur de ` Employee `, qui prend un identifiant d’employé et un nom, les méthodes `setId()` et `setName()` sont toutes deux appelées, mais elles ne provoquent pas de copie à l’écriture, car le compteur de références de l’objet ` EmployeeData ` nouvellement construit vient d’être mis à 1.

Dans les fonctions membres const de Employee, la déréférence du pointeur d ne provoque 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 la méthode ` operator=() ` se contente d’incrémenter le compteur de références de l’objet partagé ` EmployeeData `.

Partage implicite vs partage explicite

Le partage implicite n’est peut-être pas adapté à 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, l’employé n° 1001. Les deux objets Employee pointent vers la même instance de EmployeeData, dont le compteur de références est égal à 2. Ensuite, la méthode e1.setName("Hans Holbein") est appelée pour modifier le nom de l’employé, mais comme le nombre de références est supérieur à 1, une copie à l’écriture est effectuée avant que le nom ne soit modifié. Désormais, e1 et e2 pointent vers des objets EmployeeData différents. Ils ont des noms différents, mais possèdent tous deux l’ID 1001, ce qui n’est probablement pas ce que vous souhaitez. Vous pouvez bien sûr simplement continuer avec e1.setId(1002) si vous souhaitez réellement créer un deuxième employé distinct, mais si vous souhaitez simplement modifier le nom de l’employé partout, envisagez d’utiliser explicit sharing dans la classe Employee au lieu du partage implicite.

Si vous déclarez le pointeur d dans la classe Employee comme étant de type QExplicitlySharedDataPointer<EmployeeData>, alors le partage explicite est utilisé et les opérations de copie à l’écriture ne sont pas effectuées automatiquement (c’est-à-dire que detach() n’est pas appelé dans les fonctions non-const). 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`, il n’y a donc qu’un seul employé portant l’ID 1001.

Dans la documentation relative aux fonctions membres, le pointeur `d` fait toujours référence au pointeur interne vers l’objet de données partagé.

Optimisation des performances pour une utilisation dans les conteneurs Qt

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

Voir également QSharedData, QExplicitlySharedDataPointer, QScopedPointer et QSharedPointer.

Documentation sur les types de membres

QSharedDataPointer::Type

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

Documentation des fonctions membres

[noexcept] QSharedDataPointer::QSharedDataPointer()

Crée un objet `QSharedDataPointer` initialisé avec ` nullptr ` comme pointeur `d`.

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

Crée un objet `QSharedDataPointer` dont le pointeur `d` est défini sur ` data ` et incrémente le compteur de références de ` data`.

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

Crée un QSharedDataPointer dont le pointeur d est défini sur data. Le compteur de références de datan' est pas incrémenté ; cette fonction peut être utilisée pour récupérer des pointeurs obtenus via take().

Cette fonction a été introduite dans Qt 6.0.

Voir également take().

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

Définit le pointeur d de cette structure sur le pointeur d de o et incrémente le compteur de références de l'objet de données partagé.

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

La fonction « move » construit une instance de `QSharedDataPointer` en la faisant pointer vers le même objet que celui vers lequel pointait ` o `.

QSharedDataPointer::~QSharedDataPointer()

Diminue le nombre de références de l'objet de données partagé. Si ce nombre devient égal à 0, l'objet de données partagé est supprimé. Il 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 compteur 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 afin 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 de modèle pour la fonction clone() appelle la fonction virtuelle EmployeeData::clone(). Une classe dérivée de EmployeeData pourrait redéfinir cette fonction et renvoyer le type polymorphe approprié.

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

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

Voir également data().

T *QSharedDataPointer::data()

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

Voir également constData().

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

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

void QSharedDataPointer::detach()

Si le compteur de références de l'objet de données partagé est supérieur à 1, cette fonction crée une copie profonde de l'objet de données partagé et attribue la valeur du pointeur `d` de celui-ci à la copie.

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

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

Identique à ` data()`. Cette fonction est fournie à des fins de compatibilité avec la 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 à des fins de compatibilité avec la 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 cet objet sur ` ptr ` et incrémente le compteur de références de ` ptr` si ` ptr ` n'est pas ` nullptr`. Le compteur de références de l'ancien objet de données partagées est décrémenté, et l'objet est supprimé si le compteur de références atteint 0.

Cette fonction a été introduite dans Qt 6.0.

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

Permute ce pointeur de données partagées avec other. Cette opération est très rapide et ne plante jamais.

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

Renvoie un pointeur vers l'objet partagé et réinitialise `this` à ` nullptr`. (Autrement dit, cette fonction définit le pointeur `d` de `this` sur ` nullptr`.)

Remarque : le compteur de références de l’objet renvoyé ne sera pas décrémenté. Cette fonction peut être utilisée conjointement avec le constructeur qui prend un objet ` QAdoptSharedDataTag ` comme argument pour transférer l’objet de données partagé sans opérations atomiques intermédiaires.

Cette fonction a été introduite dans Qt 6.0.

QSharedDataPointer::operator T *()

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

Voir également data() et constData().

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

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

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

Renvoie ` true ` si le pointeur `d` de cette instance est ` nullptr`.

T &QSharedDataPointer::operator*()

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

const T &QSharedDataPointer::operator*() const

Permet d'accéder en lecture seule aux membres de l'objet de données partagé. Cette fonction n'appelle pas la méthode ` detach()`.

T *QSharedDataPointer::operator->()

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

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

Permet d'accéder en lecture seule aux membres de l'objet de données partagé. Cette fonction n'appelle pas la méthode ` detach()`.

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

Cette opération attribue l'other à cette instance d'QSharedDataPointer.

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

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

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

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

Éléments non membres associé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 » ne pointent pas vers le même pointeur `d`. Cette fonction n' appelle pas la fonction « 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 la fonction ` detach()`.

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

Renvoie « true » si « lhs » et « rhs » pointent vers le même pointeur `d`. Cette fonction n' appelle pas la fonction « 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.