概述

槽函数内频繁申请内存问题

[toc]

槽函数中重复 new

这个问题比骄常见,举一个简单的例子:

connect(timer, &Qtimer::timeout, this, &this::slotCreateItem);
 
void slotCreateItem()
{
    QWidget *widget = new QWidget();
}
 
timer->start(1000);

上边只是为了说明一下类似的这种情况,由于一些特殊原因导致的槽函数中会多次触发 new 操作。

解决办法

  1. 设置为成员变量,在进入函数时,先执行 delete ,再去 new

    void slotCreateItem()
    {
        if(nullptr == m_widget)
        {
            delete m_widget;
            m_widget = nullptr;
        }
        m_widget = new QWidget();
    }
  2. 第二种办法就是设置控件属性

    void slotCreateItem()
    {
        QWidget *widget = new QWidget();
        widget->setAttribute(WA_DeleteOnClose);
    }

槽函数多次绑定问题

connect(timer, &QTimer::timeout, this, &this::slotCreateItem);
 
void slotCreateItem()
{
	connect(timer, &QTimer::timeout, this, &this::slotRePaint); // 每进入一次就会绑定一次,每绑定一次,触发次数就会增加一次
}

解决办法

使用 Qt 的第五个参数控制。将上述代码改为以下形式

	connect(timer, &QTimer::timeout, this, &this::slotRePaint, Qt::UniqueConnection); // (modify)每进入一次就会绑定一次,每绑定一次,触发次数就会增加一次

Qt::UniqueConnection:这是一个标记,可以使用位或与上述任何一种连接类型结合使用。当 Qt::UniqueConnection 被设置后,如果连接已经存在,QObject::connect() 将会失败(即,如果相同的信号已经为同一对对象连接到相同的槽位)。这个标志是在Qt 4.6中引入的。

以下为 Qt 第五个参数各个含义:

常量描述
Qt::AutoConnection0(默认)如果接收器位于发出信号的线程中,则使用Qt::DirectConnection。否则,使用Qt::QueuedConnection。连接类型是在信号发出时确定的。
Qt::DirectConnection1发出信号时立即调用插槽。槽在信令线程中执行。
Qt::QueuedConnection2当控制返回到接收方线程的事件循环时,将调用插槽。插槽在接收方的线程中执行。
Qt::BlockingQueuedConnection3与Qt::QueuedConnection相同,除了信令线程阻塞直到插槽返回。如果接收端位于信令线程中,则绝不能使用此连接,否则应用程序将死锁。
Qt::UniqueConnection0x80这是一个标记,可以使用位或与上述任何一种连接类型结合使用。当Qt::UniqueConnection被设置后,如果连接已经存在,QObject::connect()将会失败