QSharedDataPointer Class
template <typename T> class QSharedDataPointerLa clase QSharedDataPointer representa un puntero a un objeto implícitamente compartido. Más...
| Cabecera: | #include <QSharedDataPointer> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Core)target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
| Hereda de: | QSharedDataPointerBase |
Esta clase es fuertemente comparable.
Esta clase es fuertemente comparable con T* y std::nullptr_t.
Nota: Todas las funciones de esta clase son reentrantes.
Tipos Públicos
Funciones Públicas
| 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) |
Funciones Protegidas
| T * | clone() |
No Miembros Relacionados
| 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) |
Descripción detallada
QSharedDataPointer<T> hace que escribir tus propias clases implícitamente compartidas sea fácil. QSharedDataPointer implementa el conteo de referencias a prueba de hilos, asegurando que añadir QSharedDataPointers a tus clases reentrantes no las hará no reentrantes.
La compartición implícita es utilizada por muchas clases Qt para combinar la velocidad y eficiencia de memoria de los punteros con la facilidad de uso de las clases. Vea la página de Clases Compartidas para más información.
Supongamos que quieres hacer una clase Employee implícitamente compartida. El procedimiento es:
- Defina la clase
Employeepara que tenga un único miembro de datos de tipoQSharedDataPointer<EmployeeData>. - Defina la clase
EmployeeDataderivada de QSharedData para que contenga todos los miembros de datos que normalmente habría puesto en la claseEmployee.
Para mostrar esto en la práctica, revisaremos el código fuente de la clase Employee compartida implícitamente. En el fichero de cabecera definimos las dos clases Employee y 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; };
En la clase Employee, observe el único miembro de datos, un puntero d de tipo QSharedDataPointer<EmployeeData>. Todos los accesos a los datos del empleado deben pasar por el puntero d de operator->(). Para los accesos de escritura, operator->() llamará automáticamente a detach(), que crea una copia del objeto de datos compartidos si el recuento de referencias del objeto de datos compartidos es mayor que 1. Esto garantiza que las escrituras en un objeto Employee no afecten a ningún otro objeto Employee que comparta el mismo objeto EmployeeData.
La clase EmployeeData hereda de QSharedData, que proporciona el contador de referencias entre bastidores. EmployeeData tiene un constructor por defecto, un constructor de copia y un destructor. Normalmente, las implementaciones triviales de estos son todo lo que se necesita en la clase de datos para una clase implícitamente compartida.
La implementación de los dos constructores de la clase Employee también es sencilla. Ambos crean una nueva instancia de EmployeeData y la asignan al puntero d.
Employee() { d = new EmployeeData; }
Employee(int id, const QString &name) {
d = new EmployeeData;
setId(id);
setName(name);
}Nótese que la clase Employee también tiene definido un constructor de copia trivial, que no es estrictamente necesario en este caso.
Employee(const Employee &other) = default; Employee &operator=(const Employee &other) = default; Employee(Employee &&other) = default; Employee &operator=(Employee &&other) = default; ~Employee() = default;
El constructor de copia no es estrictamente necesario aquí, porque la clase EmployeeData está incluida en el mismo fichero que la clase Employee (employee.h). Sin embargo, incluir la subclase privada de QSharedData en el mismo fichero que la clase pública que contiene el QSharedDataPointer no es típico. Normalmente, la idea es ocultar la subclase privada de QSharedData al usuario poniéndola en un fichero separado que no se incluiría en el fichero público. En este caso, normalmente pondríamos la clase EmployeeData en un fichero separado, que no se incluiría en employee.h. En su lugar, simplemente predeclararíamos la subclase privada EmployeeData en employee.h de esta forma:
class EmployeeData;Si lo hubiéramos hecho así aquí, el constructor de copia mostrado sería necesario. Como el constructor de copia es trivial, es mejor incluirlo siempre.
Entre bastidores, QSharedDataPointer incrementa automáticamente la cuenta de referencias cada vez que un objeto Employee es copiado, asignado o pasado como parámetro. Disminuye la cuenta de referencias siempre que un objeto Employee es borrado o sale del ámbito. El objeto EmployeeData compartido se elimina automáticamente cuando el recuento de referencias llega a 0.
En una función miembro no-const de Employee, siempre que el puntero d es dereferenciado, QSharedDataPointer llama automáticamente a detach() para asegurar que la función opera en su propia copia de los datos.
void setId(int id) { d->id = id; } void setName(const QString &name) { d->name = name; }
Tenga en cuenta que si detach() es llamado más de una vez en una función miembro debido a múltiples desreferencias del puntero d, detach() sólo creará una copia de los datos compartidos la primera vez que sea llamado, si es que lo hace, porque en la segunda y posteriores llamadas de detach(), el recuento de referencias será 1 de nuevo.
Pero observe que en el segundo constructor de Employee, que toma un ID de empleado y un nombre, se llama tanto a setId() como a setName(), pero no causan copia al escribir, porque la cuenta de referencias para el objeto EmployeeData recién construido acaba de ser puesta a 1.
En las funciones const de Employee, la desreferenciación del puntero d no provoca la llamada a detach().
int id() const { return d->id; } QString name() const { return d->name; }
Observe que no hay necesidad de implementar un constructor de copia o un operador de asignación para la clase Employee, porque el constructor de copia y el operador de asignación proporcionados por el compilador C++ harán la copia superficial miembro por miembro requerida. El único miembro a copiar es el puntero d, que es un QSharedDataPointer, cuyo operator=() sólo incrementa la cuenta de referencias del objeto compartido EmployeeData.
Compartición implícita vs explícita
La compartición implícita puede no ser adecuada para la clase Employee. Consideremos un ejemplo simple que crea dos instancias de la clase Employee compartida implícitamente.
#include "employee.h" int main() { Employee e1(1001, "Albrecht Durer"); Employee e2 = e1; e1.setName("Hans Holbein"); }
Después de crear el segundo empleado e2 y asignarle e1, tanto e1 como e2 hacen referencia a Albrecht Durer, empleado 1001. Ambos objetos Employee apuntan a la misma instancia de EmployeeData, que tiene la cuenta de referencia 2. A continuación, se llama a e1.setName("Hans Holbein") para cambiar el nombre del empleado, pero como el número de referencias es mayor que 1, se realiza una copia en escritura antes de cambiar el nombre. Ahora e1 y e2 apuntan a diferentes objetos EmployeeData. Tienen nombres diferentes, pero ambos tienen el ID 1001, que probablemente no es lo que quieres. Puedes, por supuesto, continuar con e1.setId(1002), si realmente quieres crear un segundo empleado único, pero si sólo quieres cambiar el nombre del empleado en todas partes, considera usar explicit sharing en la clase Employee en lugar de compartir implícitamente.
Si declara el puntero d en la clase Employee como QExplicitlySharedDataPointer<EmployeeData>, entonces se utiliza la compartición explícita y las operaciones de copia en escritura no se realizan automáticamente (es decir, no se llama a detach() en funciones no-const). En ese caso, después de e1.setName("Hans Holbein"), el nombre del empleado ha cambiado, pero tanto e1 como e2 siguen haciendo referencia a la misma instancia de EmployeeData, por lo que sólo hay un empleado con ID 1001.
En la documentación de las funciones miembro, el puntero d siempre se refiere al puntero interno al objeto de datos compartidos.
Optimizar el rendimiento para su uso en contenedores Qt
Debería considerar marcar su clase implícitamente compartida como un tipo movible utilizando la macro Q_DECLARE_TYPEINFO() si se parece a la clase Employee anterior y utiliza un QSharedDataPointer o QExplicitlySharedDataPointer como único miembro. Esto puede mejorar el rendimiento y la eficiencia de memoria al utilizar las clases contenedoras de Qt.
Ver también QSharedData, QExplicitlySharedDataPointer, QScopedPointer, y QSharedPointer.
Documentación de Tipos de Miembros
QSharedDataPointer::Type
Es el tipo del objeto de datos compartidos. El puntero d apunta a un objeto de este tipo.
Documentación de las funciones miembro
[noexcept] QSharedDataPointer::QSharedDataPointer()
Construye un QSharedDataPointer inicializado con nullptr como puntero d.
[explicit noexcept] QSharedDataPointer::QSharedDataPointer(T *data)
Construye un QSharedDataPointer con el puntero d establecido a data e incrementa la cuenta de referencias de data.
[noexcept, since 6.0] QSharedDataPointer::QSharedDataPointer(T *data, QAdoptSharedDataTag)
Construye un QSharedDataPointer con el puntero d fijado a data. El contador de referencia de datano se incrementa; esto puede usarse para adoptar punteros obtenidos de take().
Esta función se introdujo en Qt 6.0.
Véase también take().
[noexcept] QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T> &o)
Establece el puntero d de this al puntero d en o e incrementa la cuenta de referencias del objeto de datos compartidos.
[noexcept] QSharedDataPointer::QSharedDataPointer(QSharedDataPointer<T> &&o)
Move-construye una instancia de QSharedDataPointer, haciendo que apunte al mismo objeto al que apuntaba o.
QSharedDataPointer::~QSharedDataPointer()
Disminuye el recuento de referencias del objeto de datos compartidos. Si el recuento de referencias llega a 0, se elimina el objeto de datos compartidos. A continuación, se destruye.
[protected] T *QSharedDataPointer::clone()
Crea y devuelve una copia profunda de los datos actuales. Esta función es llamada por detach() cuando el recuento de referencias es mayor que 1 para crear la nueva copia. Esta función utiliza el operador new y llama al constructor de copia del tipo T.
Esta función se proporciona para que puedas soportar "constructores de copia virtuales" para tus propios tipos. Para ello, debe declarar una especialización de plantilla de esta función para su propio tipo, como en el ejemplo siguiente:
template<> EmployeeData *QSharedDataPointer<EmployeeData>::clone() { return d->clone(); }
En el ejemplo anterior, la especialización de plantilla para la función clone() llama a la función virtual EmployeeData::clone(). Una clase derivada de EmployeeData podría anular esa función y devolver el tipo polimórfico apropiado.
[noexcept] const T *QSharedDataPointer::constData() const
Devuelve un puntero constante al objeto de datos compartidos. Esta función no llama a detach().
Véase también data().
T *QSharedDataPointer::data()
Devuelve un puntero al objeto de datos compartidos. Esta función llama a detach().
Véase también constData().
[noexcept] const T *QSharedDataPointer::data() const
Devuelve un puntero al objeto de datos compartidos. Esta función no llama a detach().
void QSharedDataPointer::detach()
Si el recuento de referencias del objeto de datos compartidos es mayor que 1, esta función crea una copia profunda del objeto de datos compartidos y establece el puntero d de éste a la copia.
Esta función es llamada automáticamente por las funciones miembro no-const de QSharedDataPointer si se requiere copia en escritura. No es necesario llamarla.
[since 6.0] T *QSharedDataPointer::get()
Igual que data(). Esta función se proporciona por compatibilidad con STL.
Esta función se introdujo en Qt 6.0.
[noexcept, since 6.0] const T *QSharedDataPointer::get() const
Igual que data(). Esta función se proporciona por compatibilidad con STL.
Esta función se introdujo en Qt 6.0.
[noexcept, since 6.0] void QSharedDataPointer::reset(T *ptr = nullptr)
Establece el puntero d de este en ptr e incrementa la cuenta de referencias de ptr'si ptr no es nullptr. La cuenta de referencia del antiguo objeto de datos compartidos se decrementa, y el objeto se elimina si la cuenta de referencia llega a 0.
Esta función se introdujo en Qt 6.0.
[noexcept] void QSharedDataPointer::swap(QSharedDataPointer<T> &other)
Intercambia este puntero de datos compartidos con other. Esta operación es muy rápida y nunca falla.
[noexcept, since 6.0] T *QSharedDataPointer::take()
Devuelve un puntero al objeto compartido, y restablece esto a nullptr. (Es decir, esta función establece el puntero d de esto a nullptr.)
Nota: La cuenta de referencias del objeto devuelto no será decrementada. Esta función puede utilizarse junto con el constructor que toma un objeto de etiqueta QAdoptSharedDataTag para transferir el objeto de datos compartidos sin operaciones atómicas intermedias.
Esta función se introdujo en Qt 6.0.
QSharedDataPointer::operator T *()
Devuelve un puntero al objeto de datos compartidos. Esta función llama a detach().
Véase también data() y constData().
[noexcept] QSharedDataPointer::operator const T *() const
Devuelve un puntero al objeto de datos compartidos. Esta función no llama a detach().
[noexcept] bool QSharedDataPointer::operator!() const
Devuelve true si el puntero d de esto es nullptr.
T &QSharedDataPointer::operator*()
Proporciona acceso a los miembros del objeto de datos compartidos. Esta función llama a detach().
const T &QSharedDataPointer::operator*() const
Proporciona acceso constante a los miembros del objeto de datos compartidos. Esta función no llama a detach().
T *QSharedDataPointer::operator->()
Proporciona acceso a los miembros del objeto de datos compartidos. Esta función llama a detach().
[noexcept] const T *QSharedDataPointer::operator->() const
Proporciona acceso constante a los miembros del objeto de datos compartidos. Esta función no llama a detach().
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(QSharedDataPointer<T> &&other)
Mover-asigna other a esta instancia QSharedDataPointer.
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(T *o)
Establece el puntero d de esto en o e incrementa la cuenta de referencias de o. La cuenta de referencia del antiguo objeto de datos compartidos de this se decrementa. Si la cuenta de referencia del antiguo objeto de datos compartidos se convierte en 0, el antiguo objeto de datos compartidos se elimina.
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(const QSharedDataPointer<T> &o)
Establece el puntero d de this al puntero d de o e incrementa la cuenta de referencia del objeto de datos compartidos. La cuenta de referencia del antiguo objeto de datos compartidos de this se decrementa. Si la cuenta de referencia del antiguo objeto de datos compartidos se convierte en 0, el antiguo objeto de datos compartidos se elimina.
No miembros relacionados
[noexcept] bool operator!=(T *const &lhs, const QSharedDataPointer<T> &rhs)
Devuelve true si el puntero d de rhs no es lhs. puntero d. Esta función no llama a detach().
[noexcept] bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
Devuelve true si lhs y rhs no tienen el mismo puntero d. Esta función no llama a detach().
[noexcept] bool operator==(T *const &lhs, const QSharedDataPointer<T> &rhs)
Devuelve true si el puntero d de rhs es lhs. Esta función no llama a detach().
[noexcept] bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
Devuelve true si lhs y rhs tienen el mismo puntero d. Esta función no llama a 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.