1. ホーム
  2. c++

[解決済み] QtのQPointer、QSharedPointer、QWeakPointerクラスの違いは何ですか?

2022-02-15 12:41:59

質問

Qtのドキュメントで、以下のように書かれています。 QPointer , QSharedPointerQWeakPointer クラスがあります。と書かれています。

  1. QPointer は Qt オブジェクトへのガード付きポインターを提供するテンプレートクラスで、参照されているオブジェクトが破壊されたときに自動的に 0 に設定され、quot; dangling pointers" が生成されないことを除いて、通常の C++ ポインターと同じように振る舞います。

  2. QSharedPointer クラスは、共有ポインタへの強い参照を保持します。

  3. QWeakPointer クラスは、共有ポインタへの弱い参照を保持します。

つまり、オブジェクトへのポインタとポインタへの参照はどう違うのでしょうか?これらはすべて、異なるメカニズムや動作を持つオブジェクトへのポインタなのでしょうか?

どのように解決するのですか?

QPointerです。
QPointer を指すことができるのは QObject インスタンスになります。これは自動的に nullptr 指されたオブジェクトが破壊された場合 に特化した弱いポインタです。 QObject .

この断片を考えてみましょう。

QObject *obj = new QObject;
QPointer<QObject> pObj(obj);
delete obj;
Q_ASSERT(pObj.isNull()); // pObj will be nullptr now

QSharedPointer
参照カウントされるポインタ。実際のオブジェクトは、すべての共有ポインタが破壊されたときにのみ削除されます。と同じです。 std::shared_ptr .

int *pI = new int;
QSharedPointer<int> pI1(pI);
QSharedPointer<int> pI2 = pI1;
pI1.clear();
// pI2 is still pointing to pI, so it is not deleted
pI2.clear();
// No shared pointers anymore, pI is deleted

共有ポインタがある限り、オブジェクトは削除されないことに注意してください!

QWeakPointerです。
共有ポインタへの弱い参照を保持することができます。これはオブジェクトの破壊を防ぐことはできず、単にリセットされるだけです。に相当します。 std::weak_ptr ここで lock は、以下のものと同等です。 toStrongRef .

int *pI = new int;
QSharedPointer<int> pI1(pI);
QWeakPointer<int> pI2 = pI1;
pI1.clear();
// No shared pointers anymore, pI is deleted
//
// To use the shared pointer, we must "lock" it for use:
QSharedPointer<int> pI2_locked = pI2.toStrongRef();
Q_ASSERT(pI2_locked.isNull());

これは、他のモジュールによって制御されているオブジェクトにアクセスする必要がある場合に使用することができます。

弱ポインタを使用するには、弱ポインタを QSharedPointer . あなたは 弱いポインタが有効かどうかで判断してはいけません。 . のみを使用することができます。 data() または isNull() を使用して、ポインタがヌルであることを判断します。

一般に、弱いポインタを使用するには、それを共有ポインタに変換する必要があります。そうすることで、使用している間、そのオブジェクトが確実に存続するようになるからです。これは、オブジェクトをロックしてアクセスすることと同じであり、弱ポインタが指すオブジェクトを使用する唯一の正しい方法です。

QScopedPointerです。
これは単なるヘルパークラスで、ポインタがスコープ外に出たときに、参照されているオブジェクトを削除します。したがって、動的に割り当てられたオブジェクトを変数スコープに束縛します。

ローカルのRAIIセマンティクスなどに利用できる。

MyClass *foo() {
    QScopedPointer<MyClass> myItem(new MyClass);
    // Some logic
    if (some condition) {
        return nullptr; // myItem will be deleted here
    }
    return myItem.take(); // Release item from scoped pointer and return it
}

例外が発生した場合、その項目も削除されます

他の使用例としては、オブジェクトのメンバー変数があります。そうすれば、それらのためのデストラクタを書く必要はありません。

class MyClass {
public:
    MyClass() : myPtr(new int) {}
private:
    QScopedPointer<int> myPtr; // Will be deleted automatically when containing object is deleted
}