QSharedDataPointer Class

template <typename T> class QSharedDataPointer

QSharedDataPointer クラスは、暗黙の共有オブジェクトへのポインタを表します。詳細...

ヘッダー #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 クラスのソース・コードを見てみましょう。ヘッダー・ファイルでは、EmployeeEmployeeData の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 のプライベート・サブクラスをパブリック・ファイルに含めない別のファイルに置くことで、ユーザーから隠します。この場合、通常はクラスEmployeeDataemployee.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 に設定されただけなので、書き込み時にコピーが発生しないことに注意してください。

Employeeconstメンバ関数では、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 がそれに割り当てられた後、e1e2 の両方が従業員 1001 の Albrecht Durer を参照しています。両方のEmployee オブジェクトは、参照カウント 2 を持つEmployeeData の同じインスタンスを指します。次に、e1.setName("Hans Holbein") が呼び出され、従業員の名前が変更されるが、参照カウントが1より大きいため、名前が変更される前に書き込み時のコピーが実行される。ここで、e1e2 は異なる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も参照してください

メンバ型のドキュメント

QSharedDataPointer::Type

これは共有データ・オブジェクトの型である。dポインタはこの型のオブジェクトを指す。

メンバ関数ドキュメント

[noexcept] QSharedDataPointer::QSharedDataPointer()

nullptrd ポインタとして初期化された 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ポインタを odポインタに設定し、共有データオブジェクトの参照カウントをインクリメントする。

[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 にセットし、ptrnullptr でない場合、ptr の参照カウントをインクリメントする。古い共有データ・オブジェクトの参照カウントがデクリメントされ、参照カウントが 0 になるとオブジェクトが削除されます。

この関数は Qt 6.0 で導入されました。

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

この共有データ・ポインターをother と交換する。この操作は非常に高速で、失敗することはない。

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

共有オブジェクトへのポインタを返し、this を nullptr にリセットする(つまり、この関数はthisd ポインタを nullptr にセットする)。

注意: 返されたオブジェクトの参照カウントはデクリメントされません。この関数は、QAdoptSharedDataTag タグ・オブジェクトを受け取るコンストラクタと一緒に使用することで、アトミック操作を介さずに共有データ・オブジェクトを転送することができます。

この関数は Qt 6.0 で導入されました。

T *QSharedDataPointer::operator T *()

共有データ・オブジェクトへのポインタを返す。この関数はdetach() を呼び出す。

data() およびconstData()も参照

[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)

thisd ポインタを o に設定し、o の参照カウントをインクリメントする。thisの古い共有データ・オブジェクトの参照カウントがデクリメントされる。古い共有データ・オブジェクトの参照カウントが0になると、古い共有データ・オブジェクトは削除される。

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

thisの dポインタを odポインタに設定し、共有データ・オブジェクトの参照カウントをインクリメントする。thisの古い共有データオブジェクトの参照カウントがデクリメントされる。古い共有データ・オブジェクトの参照カウントが0になると、古い共有データ・オブジェクトは削除される。

関連する非会員

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

lhsrhs が同じd ポインタない場合、true を返す。この関数はdetach() を呼び出さない

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

rhsd ポインタが ptrd ポインタない場合、true を返す。この関数はdetach() を呼び出さない

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

lhsrhs が同じd ポインタの場合、true を返す。この関数はdetach() を呼び出さない

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

rhsd ポインタが 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.