1

私は現在、このようなものを持っています

QSharedPointer<QMainWindow> cv;

この共有ポインタは次のように使用されます。

cV = QSharedPointer<QMainWindow>(new QMainWindow(p));
cV->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose);
cV->show();

を閉じるとQMainWindow、次のコードでアプリがクラッシュします

if(cV)
    cV->close(); //This pointer is no longer valid.

私の質問は、cV QMainWindow(の x ボタンをクリックして) オブジェクトを閉じたときに、次のステートメントが true を返すのはなぜですか?

if(cV)

falseウィンドウが閉じられている場合、どうすれば元に戻すことができますか?

4

2 に答える 2

5

共有ポインタは、それが指しているオブジェクトをいつ削除するかを魔法のように知りません。共有ポインタによって有効期間が管理されているオブジェクトを手動で削除するとエラーになります。ウィンドウは閉じられると自動的に削除されるため、ぶら下がっている共有ポインターが得られます。

QSharedPointerしたがって、のウィジェットでは使用できませんQt::WA_DeleteOnClose

必要なのは、ウィジェットがまだ存在するかどうかを追跡するポインタです。そのようなポインターはQPointerであり、必要なことを正確に実行します。QObjectそのポインターは、 aが破棄されたときに自身をゼロにリセットするように設計されています。

は弱いポインターであることに注意してQPointerください。ウィンドウがスコープ外に出てもウィンドウは削除されません。

基になる を削除できる所有ポインタが必要な場合は、次QObjectの方法があります。

template <typename T> class ScopedQObjectPointer {
  Q_DISABLE_COPY(ScopedQObjectPointer)
  QPointer<T> m_ptr;
  inline void check() const {
    Q_ASSERT(m_ptr && (m_ptr->thread() == 0
             || m_ptr->thread() == QThread::currentThread()));
  }
public:
  explicit ScopedQObjectPointer(T* obj = 0) : m_ptr(obj) {}
  ScopedQObjectPointer(ScopedQObjectPointer &&other) : m_ptr(other.take()) {}
  ~ScopedQObjectPointer() { check(); delete m_ptr; }
  operator T*() const { check(); return m_ptr; }
  T & operator*() const { check(); return *m_ptr; }
  T * operator->() const { check(); return m_ptr; }
  T * data() const { check(); return m_ptr; }
  T * take() { check(); T * p = m_ptr; m_ptr.clear(); return p; }
  void reset(T * other) { check(); delete m_ptr; m_ptr = other; }
  operator bool() const { check(); return m_ptr; }
};

ポインタ以外の方法でオブジェクトの削除を許可しているため、複数のスレッドからオブジェクトにアクセスするとエラーになります。オブジェクトが別のスレッドで削除される場合、null チェックと逆参照されたオブジェクトの使用の間に競合状態が発生します。したがって、 a QPointer、または aScopedObjectPointerは、オブジェクトのスレッドからのみ使用できます。これは明示的に主張されています。はQ_ASSERTリリース ビルドではノーオペレーションになり、パフォーマンスへの影響はありません。

于 2014-08-14T23:52:05.030 に答える