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 |
注意:このクラスの関数はすべてリエントラントです。
パブリック型
パブリック関数
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) |
保護された関数
T * | clone() |
関連する非メンバー
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) |
詳細説明
QSharedDataPointer<T> は、独自の暗黙的な共有クラスを簡単に記述できるようにします。QSharedDataPointer はスレッドセーフな参照カウントを実装しており、リエントラントなクラスに QSharedDataPointer を追加してもリエントラントでなくなることはありません。
暗黙的な共有は、ポインタの速度とメモリ効率とクラスの使いやすさを組み合わせるために、多くの Qt クラスで使用されています。詳細は共有クラスのページを参照してください。
Employee
クラスを暗黙の共有にしたいとします。その手順は
QSharedDataPointer<EmployeeData>
型のデータ・メンバを1つ持つようにEmployee
クラスを定義します。- QSharedData から派生した
EmployeeData
クラスを定義し、通常Employee
クラスに入れるはずのデータ・メンバをすべて入れます。
これを実際に示すために、暗黙的に共有されているEmployee
クラスのソース・コードを見てみましょう。ヘッダー・ファイルでは、Employee
とEmployeeData
の2つのクラスを定義します。
#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; };
クラスEmployee
では、単一のデータ・メンバ、QSharedDataPointer<EmployeeData>
型のd ポインタに注目してください。社員データへのアクセスはすべて、dポインターの operator->()
を経由しなければならない。書き込みアクセスの場合、operator->()
は自動的にdetach() を呼び出します。共有データ・オブジェクトの参照カウントが1より大きい場合、共有データ・オブジェクトのコピーが作成されます。これにより、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) : d (other.d) { }
クラスEmployeeData
はクラスEmployee
(employee.h
) と同じファイルに含まれているため、コピーコンストラクタはここでは厳密には必要ありません。しかし、QSharedData のプライベート・サブクラスを、QSharedDataPointer を含むパブリック・クラスと同じファイルに含めることは、一般的ではありません。通常は、QSharedData のプライベート・サブクラスをパブリック・ファイルに含めない別のファイルに置くことで、ユーザーから隠します。この場合、通常はクラスEmployeeData
をemployee.h
に含まれない別のファイルに置きます。その代わりに、employee.h
でプライベート・サブクラスEmployeeData
を事前宣言します:
class EmployeeData;
もしこのようにした場合、コピー・コンストラクタが必要になる。コピー・コンストラクタは些細なものなので、常に含めるようにした方がよいでしょう。
舞台裏では、QSharedDataPointerは、Employee
オブジェクトがコピーされたり、代入されたり、パラメータとして渡されたりするたびに、参照カウントを自動的にインクリメントします。QSharedDataPointerは、Employee
オブジェクトが削除されたり、スコープ外になるたびに、参照カウントをデクリメントします。参照カウントが 0 になると、共有されたEmployeeData
オブジェクトは自動的に削除されます。
Employee
の非 const メンバ関数では、d ポインタが再参照されるたびに、QSharedDataPointer は自動的にdetach() を呼び出し、関数がデータの独自のコピーで動作するようにします。
void setId(int id) { d->id = id; } void setName(const QString &name) { d->name = name; }
detachd ポインタの複数回の再参照により、メンバ関数内でdetach() が複数回呼び出された場合、detach() が共有データのコピーを作成するのは、それが最初に呼び出されたときだけである。
しかし、2 番目のEmployee
コンストラクタでは、従業員 ID と名前を取り、setId() と setName() の両方が呼び出されますが、新しく構築されたEmployeeData
オブジェクトの参照カウントが 1 に設定されただけなので、書き込み時にコピーが発生しないことに注意してください。
Employee
のconstメンバ関数では、d ポインタを再参照してもdetach() は呼び出されない。
int id() const { return d->id; } QString name() const { return d->name; }
C++コンパイラが提供するコピー・コンストラクタと代入演算子は、必要なメンバごとの浅いコピーを行うので、Employee
クラスにコピー・コンストラクタや代入演算子を実装する必要はないことに注意してください。コピーする唯一のメンバーは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 の Albrecht Durer を参照しています。両方のEmployee
オブジェクトは、参照カウント 2 を持つEmployeeData
の同じインスタンスを指します。次に、e1.setName("Hans Holbein")
が呼び出され、従業員の名前が変更されるが、参照カウントが1より大きいため、名前が変更される前に書き込み時のコピーが実行される。ここで、e1
とe2
は異なるEmployeeData
オブジェクトを指している。名前は違いますが、どちらもIDは1001です。もちろん、本当に2人目のユニークな従業員を作成するのであれば、e1.setId(1002)
をそのまま続けることもできますが、従業員の名前をどこでも変更したいだけであれば、暗黙的な共有ではなく、Employee
クラスでexplicit sharing を使用することを検討してください。
Employee
クラスのd ポインタを QExplicitlySharedDataPointer<EmployeeData>
と宣言すると、明示的共有が使用され、書き込み操作時のコピーは自動的には実行されません(つまり、detach() は非 const 関数では呼び出されません)。この場合、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
をd ポインタとして初期化された QSharedDataPointer を構築します。
[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ポインタに設定し、共有データオブジェクトの参照カウントをインクリメントする。
[noexcept]
QSharedDataPointer::QSharedDataPointer(QSharedDataPointer<T> &&o)
Move-QSharedDataPointerインスタンスを構築し、o が指していたのと同じオブジェクトを指すようにする。
QSharedDataPointer::~QSharedDataPointer()
共有データ・オブジェクトの参照カウントを減少させる。参照カウントが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ポインタをコピーに設定する。
この関数は、書き込み時のコピーが必要な場合、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)
この dポインタを ptr にセットし、ptr がnullptr
でない場合、ptr の参照カウントをインクリメントする。古い共有データ・オブジェクトの参照カウントがデクリメントされ、参照カウントが 0 になるとオブジェクトが削除されます。
この関数は Qt 6.0 で導入されました。
[noexcept]
void QSharedDataPointer::swap(QSharedDataPointer<T> &other)
この共有データ・ポインターをother と交換する。この操作は非常に高速で、失敗することはない。
[noexcept, since 6.0]
T *QSharedDataPointer::take()
共有オブジェクトへのポインタを返し、this を nullptr
にリセットする(つまり、この関数はthisのd ポインタを nullptr
にセットする)。
注意: 返されたオブジェクトの参照カウントはデクリメントされません。この関数は、QAdoptSharedDataTag タグ・オブジェクトを受け取るコンストラクタと一緒に使用することで、アトミック操作を介さずに共有データ・オブジェクトを転送することができます。
この関数は Qt 6.0 で導入されました。
T *QSharedDataPointer::operator T *()
共有データ・オブジェクトへのポインタを返す。この関数はdetach() を呼び出す。
[noexcept]
const T *QSharedDataPointer::operator const T *() const
共有データ・オブジェクトへのポインタを返す。この関数はdetach() を呼び出さない。
[noexcept]
bool QSharedDataPointer::operator!() const
thisの 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)
Move-other をこのQSharedDataPointer インスタンスに割り当てる。
[noexcept]
QSharedDataPointer<T> &QSharedDataPointer::operator=(T *o)
thisのd ポインタを o に設定し、o の参照カウントをインクリメントする。thisの古い共有データ・オブジェクトの参照カウントがデクリメントされる。古い共有データ・オブジェクトの参照カウントが0になると、古い共有データ・オブジェクトは削除される。
[noexcept]
QSharedDataPointer<T> &QSharedDataPointer::operator=(const QSharedDataPointer<T> &o)
thisの dポインタを o のdポインタに設定し、共有データ・オブジェクトの参照カウントをインクリメントする。thisの古い共有データオブジェクトの参照カウントがデクリメントされる。古い共有データ・オブジェクトの参照カウントが0になると、古い共有データ・オブジェクトは削除される。
関連する非会員
[noexcept]
bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
lhs とrhs が同じd ポインタでない場合、true
を返す。この関数はdetach() を呼び出さない。
[noexcept]
bool operator!=(const T *ptr, const QSharedDataPointer<T> &rhs)
rhs のd ポインタが ptr のd ポインタでない場合、true
を返す。この関数はdetach() を呼び出さない。
[noexcept]
bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
lhs とrhs が同じd ポインタの場合、true
を返す。この関数はdetach() を呼び出さない。
[noexcept]
bool operator==(const T *ptr, const QSharedDataPointer<T> &rhs)
rhs のd ポインタが ptr の場合、true
を返す。この関数はdetach() を呼び出さない。
© 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.