Qt中QScopedPointer的用法,實操驗證。


還是老規矩,QScopedPointer概念性的東西我就不贅述了,網上百度一抓一大把。

這里主要用實際的例子來說明一下QScopedPointer這個智能指針中data()和take()的用法,這里面是有坑的。

我們先來說一下data()和take()分別表示的是什么意思?

首先你可以把QScopedPointer看成是一個容器。

take()接口的意思是從這個容器中將對象刪除,並返回之前放在這個容器中的對象或者數據,QScopedPointer不再擁有這個對象的指針。

data()接口的意思就是返回容器中的指針,QScopedPointer還是擁有這個對象的指針的。

這個take()感覺用起來有點像qt中隊列(queue)的取操作(dequeue)。

有一種情況我們需要考慮的,就是在函數中使用了QScopedPointer如果來避免野指針的情況,本篇文章主要就是解決這個問題。

 

實際的例子是這樣的,我先在.h中定義了一個單例模式的接口。

static ScreenWidget *Instance();

然后在.cpp文件中實現這個接口

QScopedPointer<ScreenWidget> ScreenWidget::self;
ScreenWidget *ScreenWidget::Instance()
{
    if (self.isNull()) 
    {
        static QMutex mutex;

        QMutexLocker locker(&mutex);

        if (self.isNull()) 
        {
            self.reset(new ScreenWidget);
        }
    }

    return self.data();
}

這里用的是data()。

在main.cpp文件中是如下使用方式。

    ScreenWidget* p1 = ScreenWidget::Instance();
    p1->showFullScreen();

這種情況程序會掛掉。

 

 

 這里就是出現了野指針的問題,因為在函數中使用data(),在函數結束以后QScopedPointer會被釋放,QScopedPointer內的對象也會被釋放,那么p1就是一個野指針了。程序自然就崩潰了。

ScreenWidget::Instance()->showFullScreen();

如果程序改成以上的樣子程序就沒什么問題。不存在野指針的情況。

 

 

QScopedPointer<ScreenWidget> ScreenWidget::self;
ScreenWidget *ScreenWidget::Instance()
{
    if (self.isNull()) 
    {
        static QMutex mutex;

        QMutexLocker locker(&mutex);

        if (self.isNull()) 
        {
            self.reset(new ScreenWidget);
        }
    }

    return self.take();
}

如果將上一段代碼的返回值改成take()。

ScreenWidget* p1 = ScreenWidget::Instance();
p1->showFullScreen();

再次使用這種方式,程序沒有問題,因為take()接口在返回的時候QScopedPointer刪除了對象,但是也保留了對象的指針。p1就不會出現野指針的情況。

ScreenWidget::Instance()->showFullScreen();

如果換成這樣的形式,程序也沒有崩潰,因為沒有指針指向的情況沒有野指針存在。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM