首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QSharedPointer不返回false

QSharedPointer不返回false
EN

Stack Overflow用户
提问于 2014-08-15 04:01:12
回答 2查看 626关注 0票数 1

我目前有类似这样的东西

代码语言:javascript
复制
QSharedPointer<QMainWindow> cv;

此共享指针用作

代码语言:javascript
复制
cV = QSharedPointer<QMainWindow>(new QMainWindow(p));
cV->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose);
cV->show();

现在,如果我关闭QMainWindow,下面的代码会使应用程序崩溃

代码语言:javascript
复制
if(cV)
    cV->close(); //This pointer is no longer valid.

我的问题是,当我关闭cV QMainWindow对象(通过单击的x按钮)时,为什么下面的语句返回true

代码语言:javascript
复制
if(cV)

如果窗口已经关闭,我如何让它返回false

EN

回答 2

Stack Overflow用户

发布于 2014-08-15 07:52:05

共享指针不会神奇地知道您何时删除它所指向的对象。手动删除其生存期由共享指针管理的对象是错误的。由于窗口在关闭时会自动删除,因此您现在可以看到悬空的共享指针。

因此,如果窗口小部件是Qt::WA_DeleteOnClose,则不能使用QSharedPointer

您需要的是一个跟踪小部件是否仍然存在的指针。这样的指针就是QPointer,它做的正是你需要的。该指针被设计为在QObject被销毁时将其自身重置为零。

请注意,QPointer是一个弱指针,当它超出范围时,它不会删除窗口。

如果您需要一个允许删除底层QObject的所属指针,有一种方法可以做到:

代码语言:javascript
复制
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检查和取消引用对象的使用之间存在竞争条件。因此,QPointerScopedObjectPointer只能在object的线程中使用。这是明确断言的。Q_ASSERT在发布版本中变成了一个无操作的版本,并且在那里没有性能影响。

票数 5
EN

Stack Overflow用户

发布于 2014-08-15 07:56:10

当所有所有者都超出范围时,由QSharedPointer保护的对象将由QSharedPointer本身删除。在本例中,您让QMainWindow在用户关闭cV时将其删除。QSharedPointer不知道该事件,也不会自动将指针设置为0。

您的解决方案很简单。忘记QSharedPointer,只使用QPointer。当您或QObject删除对象时,QPointer会自动将指针设置为0。然后可以在(cV)的情况下使用

代码语言:javascript
复制
class foo {  

public:
  ~foo() {      
    delete cV; // delete cV if cV is not 0.
  }

  void showMainWindow() {
    if ( ! cV) {
      cV = new QMainWindow();
      cV->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose);
    }
    cV->show();
  }
  void closeMainWindow() {
    if (cV) { // cV is 0 if it is already deleted when user closes it
      cV->close();
    }
  }

private:
  QPointer<QMainWindow> cV;
};

如果你想避免析构函数中的删除,并在cV超出范围时自动删除它,你可以在这个问题的另一个答案中使用KubarOber的ScopedQObjectPointer

代码语言:javascript
复制
class foo {  

public:
  ~foo() {      
  }

  void showMainWindow() {
    if ( ! cV) {
      cV.reset(new QMainWindow());
      cV->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose);
    }
    cV->show();
  }
  void closeMainWindow() {
    if (cV) { // cV is 0 if it is already deleted when user closes it
      cV->close();
    }
  }

private:
  ScopedQObjectPointer<QMainWindow> cV;
};

编辑:我刚刚注意到您在创建cV:新的QMainWindow(p)时使用了父级。如果p不为空,那么当p被删除时,p也会删除cV。所以即使你使用QPointer,也不需要删除析构函数中的cV。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25316632

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档