QSharedDataPointer Class
template <typename T> class QSharedDataPointerQSharedDataPointer クラスは、暗黙的に共有されるオブジェクトへのポインタを表します。詳細...
| ヘッダー: | #include <QSharedDataPointer> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
| 継承元: | QSharedDataPointerBase |
注:このクラスのすべての関数は再入可能である。
QSharedDataPointer の比較
| カテゴリ | 比較可能な型 |
|---|---|
| strong | QSharedDataPointer |
| strong | T* および std::nullptr_t。 |
パブリック型
パブリック関数
| 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) |
保護された関数
| 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) |
詳細な説明
QSharedDataPointer は、テンプレートパラメータ `T ` によって、QSharedData から派生する共有データクラスの型が指定されるテンプレートクラスです。
QSharedDataPointer<T> を使用すると、独自の暗黙的に共有されるクラスを簡単に作成できます。QSharedDataPointerはスレッドセーフな参照カウントを実装しており、再入可能クラスに QSharedDataPointer を追加しても、そのクラスが再入不可能になることはありません。
暗黙的な共有は、ポインタの速度とメモリ効率をクラスの使いやすさと組み合わせるために、多くの Qt クラスで使用されています。詳細については、「共有クラス」のページを参照してください。
Employee クラスを暗黙的に共有したい場合、手順は次のとおりです。
Employeeクラスを、QSharedDataPointer<EmployeeData>型のデータメンバーを1つ持つように定義します。- `QSharedData ` から派生した `
EmployeeData` クラスを定義し、通常なら `Employee` クラスに含めるはずだったすべてのデータメンバーをこのクラスに含めます。
これを実際に示すために、暗黙的に共有されるEmployee クラスのソースコードを確認します。ヘッダーファイルでは、Employee クラスとEmployeeData クラスの2つのクラスを定義します。
#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;
};Employee クラスには、QSharedDataPointer<EmployeeData> 型のd ポインタという単一のデータメンバーがあることに注目してください。従業員データへのすべてのアクセスは、d ポインタの operator->() を経由する必要があります。書き込みアクセスについては、operator->() が自動的にdetach() を呼び出し、共有データオブジェクトの参照カウントが 1 より大きい場合は、その共有データオブジェクトのコピーを作成します。 これにより、あるEmployee オブジェクトへの書き込みが、同じEmployeeData オブジェクトを共有する他のEmployee オブジェクトに影響を与えないことが保証されます。
クラスEmployeeData は、内部で参照カウンタを提供するQSharedData を継承しています。EmployeeData には、デフォルトコンストラクタ、コピーコンストラクタ、およびデストラクタがあります。通常、暗黙的に共有されるクラスのデータクラスでは、これらを単純に実装するだけで十分です。
Employee クラスの 2 つのコンストラクタの実装も簡単です。どちらもEmployeeData の新しいインスタンスを作成し、それをd ポインタに代入します。
Employee() { d = new EmployeeData; }
Employee(int id, const QString &name) {
d = new EmployeeData;
setId(id);
setName(name);
}なお、Employee クラスには自明なコピーコンストラクタも定義されていますが、このケースでは厳密には必須ではありません。
Employee(const Employee &other) = default;
Employee &operator=(const Employee &other) = default;
Employee(Employee &&other) = default;
Employee &operator=(Employee &&other) = default;
~Employee() = default;ここでコピーコンストラクタが厳密には必須ではないのは、クラス `EmployeeData ` がクラス `Employee ` と同じファイルに含まれているためです(employee.h )。ただし、`QSharedData ` のプライベートなサブクラスを、`QSharedDataPointer` を含むパブリッククラスと同じファイルに含めることは一般的ではありません。 通常、QSharedData のプライベートなサブクラスは、パブリックなファイルにはインクルードされない別のファイルに配置することで、ユーザーから隠すのが一般的です。この場合、通常はクラスEmployeeData を、employee.h にはインクルードされない別のファイルに配置します。その代わりに、プライベートなサブクラスEmployeeData をemployee.h 内で次のように事前宣言します:
class EmployeeData;もしここでそのようにしていた場合、示されているコピーコンストラクタが必要となります。コピーコンストラクタは自明なものであるため、常に含めておくのが無難でしょう。
内部的には、QSharedDataPointerは、Employee オブジェクトがコピー、代入、またはパラメータとして渡されるたびに、参照カウントを自動的にインクリメントします。また、Employee オブジェクトが削除されたり、スコープ外になったりすると、参照カウントをデクリメントします。共有されているEmployeeData オブジェクトは、参照カウントが0になった時点で自動的に削除されます。
Employee の非constメンバー関数において、dポインタが間接参照されるたびに、QSharedDataPointerは自動的にdetach()を呼び出し、関数がデータの独自のコピーに対して操作を行うようにします。
void setId(int id) { d->id = id; }
void setName(const QString &name) { d->name = name; }なお、dポインタが複数回参照解除されることにより、メンバー関数内でdetach()が複数回呼び出された場合、detach()は、最初の呼び出し時のみ(もし呼び出されるのであれば)共有データのコピーを作成します。これは、detach()の2回目以降の呼び出しでは、参照カウントが再び1になるためです。
ただし、従業員IDと名前を受け取る2つ目のEmployee コンストラクタでは、setId()とsetName()の両方が呼び出されますが、新しく構築されたEmployeeData オブジェクトの参照カウントが1に設定されたばかりであるため、コピーオンライトは発生しません。
Employee のconstメンバ関数において、d ポインタを間接参照しても、detach()は呼び出されません。
int id() const { return d->id; }
QString name() const { return d->name; }Employee クラスには、コピーコンストラクタや代入演算子を実装する必要はありません。C++ コンパイラが提供するコピーコンストラクタと代入演算子が、必要なメンバーごとの浅いコピーを自動的に行うためです。コピーする必要がある唯一のメンバーはd ポインタであり、これは QSharedDataPointer です。そのoperator=() は、共有されているEmployeeData オブジェクトの参照カウントを単にインクリメントするだけです。
暗黙的共有と明示的共有
暗黙的な共有は、Employee クラスには適していない可能性があります。暗黙的に共有されるEmployee クラスのインスタンスを2つ作成する簡単な例を考えてみましょう。
#include "employee.h"
int main()
{
Employee e1(1001, "Albrecht Durer");
Employee e2 = e1;
e1.setName("Hans Holbein");
}2人目の従業員 e2 が作成され、e1 がそれに割り当てられた後、e1 とe2 の両方が、従業員番号 1001 のアルブレヒト・デューラーを指すようになります。両方のEmployee オブジェクトは、参照カウントが 2 であるEmployeeData の同じインスタンスを指しています。 その後、e1.setName("Hans Holbein") が呼び出されて従業員の名前が変更されますが、参照カウントが1より大きいため、名前が変更される前にコピー・オン・ライトが実行されます。これにより、e1 とe2 は異なるEmployeeData オブジェクトを指すようになります。名前は異なりますが、どちらもIDは1001となっており、おそらくこれは意図した結果ではないでしょう。 もちろん、本当に2人目の一意な従業員を作成したいのであれば、e1.setId(1002) のままで続けても構いませんが、単に従業員の名前をすべての場所で変更したいだけなら、Employee クラス内で暗黙的な共有の代わりにexplicit sharing を使用することを検討してください。
Employee クラスでdポインタを QExplicitlySharedDataPointer<EmployeeData> として宣言すると、明示的な共有が使用され、コピーオンライト操作は自動的に実行されません(つまり、非const関数ではdetach()は呼び出されません)。 その場合、e1.setName("Hans Holbein") の実行後、従業員の名前は変更されていますが、e1とe2はどちらもEmployeeData の同じインスタンスを参照し続けているため、ID 1001の従業員は1人しか存在しません。
メンバ関数のドキュメントによると、ポインタ dは常に共有データオブジェクトへの内部ポインタを指しています。
Qtコンテナでの使用に向けたパフォーマンスの最適化
上記のEmployee クラスに類似しており、唯一のメンバとしてQSharedDataPointerまたはQExplicitlySharedDataPointer を使用している場合は、Q_DECLARE_TYPEINFO()マクロを使用して、暗黙的に共有されるクラスを移動可能な型としてマークすることを検討すべきです。これにより、Qtのコンテナクラスを使用する際のパフォーマンスとメモリ効率が向上します。
関連項目: QSharedData 、QExplicitlySharedDataPointer 、QScopedPointer 、およびQSharedPointer 。
メンバ関数のドキュメント
[noexcept] QSharedDataPointer::QSharedDataPointer()
nullptr で初期化されたQSharedDataPointerを、dポインタとして構築します。
[explicit noexcept] QSharedDataPointer::QSharedDataPointer(T *data)
d ポインタを`data ` に設定した QSharedDataPointer を生成し、data の参照カウントをインクリメントします。
[noexcept, since 6.0] QSharedDataPointer::QSharedDataPointer(T *data, QAdoptSharedDataTag)
d ポインタを`data` に設定した QSharedDataPointer を生成します。data の参照カウンタはインクリメントされません。これは、take() から取得したポインタを取り込む際に使用できます。
この関数は Qt 6.0 で導入されました。
take()も参照してください 。
[noexcept] QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T> &o)
このオブジェクトのd ポインタを、o 内のd ポインタに設定し、共有データオブジェクトの参照カウントを 1 増やします。
[noexcept] QSharedDataPointer::QSharedDataPointer(QSharedDataPointer<T> &&o)
QSharedDataPointerのインスタンスをムーブコンストラクタで生成し、o が指していたのと同じオブジェクトを指すようにします。
QSharedDataPointer::~QSharedDataPointer()
共有データオブジェクトの参照カウントを1減らします。参照カウントが0になると、その共有データオブジェクトは削除されます。その後、そのオブジェクトは破棄されます。
[protected] T *QSharedDataPointer::clone()
現在のデータのディープコピーを作成して返します。この関数は、参照カウントが 1 より大きい場合に、detach() によって呼び出され、新しいコピーを作成するために使用されます。この関数は演算子 newを使用し、型T のコピーコンストラクタを呼び出します。
この関数は、独自の型に対して「仮想コピーコンストラクタ」をサポートできるように提供されています。そのためには、以下の例のように、独自の型に対してこの関数のテンプレート特化を宣言する必要があります。
template<>
EmployeeData *QSharedDataPointer<EmployeeData>::clone()
{
return d->clone();
}上記の例では、clone() 関数のテンプレート特化がEmployeeData::clone()仮想関数を呼び出しています。EmployeeData を継承したクラスは、その関数をオーバーライドして、適切な多態型を返すことができます。
[noexcept] const T *QSharedDataPointer::constData() const
共有データオブジェクトへのconstポインタを返します。この関数は、detach()を呼び出しません。
data()も参照してください 。
T *QSharedDataPointer::data()
共有データオブジェクトへのポインタを返します。この関数は、detach() を呼び出します。
constData()も参照してください 。
[noexcept] const T *QSharedDataPointer::data() const
共有データオブジェクトへのポインタを返します。この関数は、detach()を呼び出しません。
void QSharedDataPointer::detach()
共有データオブジェクトの参照カウントが 1 より大きい場合、この関数は共有データオブジェクトのディープコピーを作成し、このオブジェクトの d ポインタをそのコピーに設定します。
この関数は、書き込み時のコピー(copy-on-write)が必要な場合、QSharedDataPointer の非constメンバ関数によって自動的に呼び出されます。自分で呼び出す必要はありません。
[since 6.0] T *QSharedDataPointer::get()
data() と同じです。この関数は、STL との互換性を確保するために提供されています。
この関数は Qt 6.0 で導入されました。
[noexcept, since 6.0] const T *QSharedDataPointer::get() const
data() と同じです。この関数は、STL との互換性を確保するために提供されています。
この関数は Qt 6.0 で導入されました。
[noexcept, since 6.0] void QSharedDataPointer::reset(T *ptr = nullptr)
ptr がnullptr でない場合、このオブジェクト のdポインタを ptr に設定し、ptr の参照カウントを1増やします。古い共有データオブジェクトの参照カウントは1減らされ、参照カウントが0になった場合はオブジェクトが削除されます。
この関数は Qt 6.0 で導入されました。
[noexcept] void QSharedDataPointer::swap(QSharedDataPointer<T> &other)
この共有データポインタをother と入れ替えます。この操作は非常に高速で、失敗することはありません。
[noexcept, since 6.0] T *QSharedDataPointer::take()
共有オブジェクトへのポインタを返し、これを nullptr にリセットします。(つまり、この関数はthisのd ポインタを nullptr に設定します。)
注: 返されるオブジェクトの参照カウントは 減算されません。この関数は、QAdoptSharedDataTag タグオブジェクトを受け取るコンストラクタと組み合わせて使用することで、アトミック操作を介さずに共有データオブジェクトを転送することができます。
この関数は Qt 6.0 で導入されました。
QSharedDataPointer::operator T *()
共有データオブジェクトへのポインタを返します。この関数は、detach() を呼び出します。
data() およびconstData()も参照してください 。
[noexcept] QSharedDataPointer::operator const T *() const
共有データオブジェクトへのポインタを返します。この関数は、detach()を呼び出しません。
[noexcept] bool QSharedDataPointer::operator!() const
このオブジェクトのd ポインタが `nullptr` である場合、true を返します。
T &QSharedDataPointer::operator*()
共有データオブジェクトのメンバへのアクセスを提供します。この関数は、detach() を呼び出します。
const T &QSharedDataPointer::operator*() const
共有データオブジェクトのメンバへのconstアクセスを提供します。この関数は、detach()を呼び出しません。
T *QSharedDataPointer::operator->()
共有データオブジェクトのメンバへのアクセスを提供します。この関数は、detach() を呼び出します。
[noexcept] const T *QSharedDataPointer::operator->() const
共有データオブジェクトのメンバへのconstアクセスを提供します。この関数はdetach()を呼び出しません。
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(QSharedDataPointer<T> &&other)
other をこのQSharedDataPointer インスタンスに割り当てます。
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(T *o)
このオブジェクトの d ポインタを`o ` に設定し、o の参照カウントを 1 増やします。このオブジェクトの古い共有データオブジェクトの参照カウントが 1 減ります。古い共有データオブジェクトの参照カウントが 0 になると、そのオブジェクトは削除されます。
[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(const QSharedDataPointer<T> &o)
このオブジェクトのd ポインタを、o のd ポインタに設定し、共有データオブジェクトの参照カウントを 1 増やします。このオブジェクトの古い共有データオブジェクトの参照カウントは 1 減らされます。古い共有データオブジェクトの参照カウントが 0 になると、そのオブジェクトは削除されます。
関連する非メンバー関数
[noexcept] bool operator!=(T *const &lhs, const QSharedDataPointer<T> &rhs)
rhs のdポインタが lhsでない場合、true を返します。dポインタ。この関数はdetach()を呼び出しません。
[noexcept] bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
lhs とrhs のd ポインタが 同一でない場合、true を返します。この関数は、detach()を呼び出しません。
[noexcept] bool operator==(T *const &lhs, const QSharedDataPointer<T> &rhs)
rhs のdポインタが lhs である場合、true を返します。この関数はdetach()を呼び出しません。
[noexcept] bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
lhs とrhs のd ポインタが同じ場合、true を返します。この関数は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.