怎么介紹自己做的企業(yè)網(wǎng)站頁面提高網(wǎng)站收錄的方法
Qt使用單例模式讀取xml文件
- 一、單例模式介紹
- 1、什么是單例模式
- 2、為什么使用單例模式
- 3、什么情況下使用單例模式
- 4、使用單例模式需要注意哪些問題
- 線程安全
- 5、單例模式的類型
- 6、單例類的特點(diǎn)
- 2、單例模式的實現(xiàn)
- 2.1懶漢式
- 2.2餓漢式
一、單例模式介紹
1、什么是單例模式
單例模式是指在整個系統(tǒng)生命周期內(nèi),保證一個類只能產(chǎn)生一個實例,確保該類的唯一性。
2、為什么使用單例模式
1、節(jié)省資源。一個類只有一個實例,不存在多份實例,節(jié)省資源。
2、方便控制。在一些操作公共資源的場景時,避免了多個對象引起的復(fù)雜操作。
3、什么情況下使用單例模式
在程序中多次使用同一個對象且作用相同時,為了防止頻繁地創(chuàng)建對象使得內(nèi)存飆升,單例模式可以讓程序僅在內(nèi)存中創(chuàng)建一個對象,讓所有需要調(diào)用的地方都共享這一單例對象。
4、使用單例模式需要注意哪些問題
線程安全
- 什么是線程安全
在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會通過同步機(jī)制保證各個線程都可以正常且正確的執(zhí)行,不會出現(xiàn)數(shù)據(jù)污染等意外情況。
- 如何保證線程安全
1、給共享的資源加把鎖,保證每個資源變量每時每刻至多被一個線程占用。
2、讓線程也擁有資源,不用去共享進(jìn)程中的資源。如:使用threadlocal可以為每個線程維護(hù)一個私有的本地變量。
5、單例模式的類型
- 懶漢式
系統(tǒng)運(yùn)行中,實例并不存在,只有當(dāng)需要使用該實例時,才會去創(chuàng)建并使用實例。這種方式要考慮線程安全。
- 餓漢式
系統(tǒng)一運(yùn)行,就初始化創(chuàng)建實例,當(dāng)需要時,直接調(diào)用即可。這種方式本身就線程安全,沒有多線程的線程安全問題。
6、單例類的特點(diǎn)
- 構(gòu)造函數(shù)和析構(gòu)函數(shù)為私有類型,目的是禁止外部構(gòu)造和析構(gòu)。
- 拷貝構(gòu)造函數(shù)和賦值構(gòu)造函數(shù)是私有類型,目的是禁止外部拷貝和賦值,確保實例的唯一性。
- 類中有一個獲取實例的靜態(tài)方法,可以全局訪問。
2、單例模式的實現(xiàn)
2.1懶漢式
加鎖的懶漢式單例(線程安全)
頭文件:
/// 加鎖的懶漢式實現(xiàn) //class SingleInstance
{public:// 獲取單實例對象static SingleInstance *GetInstance();//釋放單實例,進(jìn)程退出時調(diào)用static void deleteInstance();//返回所有的IPQVariantList getIP(){return m_ips;}//獲取XML文件bool initalize();// 打印實例地址void Print();private:// 將其構(gòu)造和析構(gòu)成為私有的, 禁止外部構(gòu)造和析構(gòu)SingleInstance();~SingleInstance();// 將其拷貝構(gòu)造和賦值構(gòu)造成為私有函數(shù), 禁止外部拷貝和賦值SingleInstance(const SingleInstance &signal);const SingleInstance &operator=(const SingleInstance &signal);//解析xml中的內(nèi)容void parseIP(const QDomNode &root);private:// 唯一單實例對象指針static SingleInstance *m_SingleInstance;static std::mutex m_Mutex;//存儲IPQVariantList m_ips;
};
源文件:
//初始化靜態(tài)成員變量
SingleInstance *SingleInstance::m_SingleInstance = nullptr;
std::mutex SingleInstance::m_Mutex;// 注意:不能返回指針的引用,否則存在外部被修改的風(fēng)險!
SingleInstance * SingleInstance::GetInstance()
{// 這里使用了兩個 if 判斷語句的技術(shù)稱為雙檢鎖;好處是,只有判斷指針為空的時候才加鎖,// 避免每次調(diào)用 GetInstance的方法都加鎖,鎖的開銷畢竟還是有點(diǎn)大的。if (m_SingleInstance == nullptr) {std::unique_lock<std::mutex> lock(m_Mutex); // 加鎖if (m_SingleInstance == nullptr){volatile auto temp = new (std::nothrow) SingleInstance();m_SingleInstance = temp;}}return m_SingleInstance;
}void SingleInstance::deleteInstance()
{std::unique_lock<std::mutex> lock(m_Mutex); // 加鎖if (m_SingleInstance){delete m_SingleInstance;m_SingleInstance = nullptr;}
}bool SingleInstance::initalize()
{QString path("目錄");QFile file(path);if(file.exists()){if(file.open(QIODevice::ReadOnly | QIODevice::Truncate)){QString error;QDomDocument document;document.setContent(&file, &error);file.close();if(document.isNull()){qDebug() << QString("文件格式異常:1%").arg(error);return false;}QDomNode root = document.firstChild();parseIP(root);}else{qDebug() << QString("%1:文件不存在,:2%").arg(path).arg(file.errorString());}}else{qDebug() QString("%1:文件不存在!").arg(path);return false;}return !m_ips.isEmpty();
}void SingleInstance::Print()
{std::cout << "我的實例內(nèi)存地址是:" << this << std::endl;
}SingleInstance::SingleInstance()
{std::cout << "構(gòu)造函數(shù)" << std::endl;
}SingleInstance::~SingleInstance()
{std::cout << "析構(gòu)函數(shù)" << std::endl;deleteInstance();
}void SingleInstance::parseIP(const QDomNode &root)
{QDomNode startnode = root.nextSibling();QDomNode node = startnode.firstChild();while(!node.isNull()){QVariantMap ips;ips.clear();QDomElement element = node.toElement();ips.insert("ip", element.attribute("ip"));ips.insert("port", element.attribute("port"));ips.insert("multiip", element.attribute("multiip"));}}
main.cpp
if(Singleton::GetInstance()->initalize())
{
...
}
2.2餓漢式
頭文件
// 餓漢實現(xiàn) /class Singleton
{
public:// 獲取單實例static Singleton* GetInstance();// 釋放單實例,進(jìn)程退出時調(diào)用static void deleteInstance();//返回所有的IPQVariantList getIP(){return m_ips;}//獲取XML文件bool initalize();// 打印實例地址void Print();private:// 將其構(gòu)造和析構(gòu)成為私有的, 禁止外部構(gòu)造和析構(gòu)Singleton();~Singleton();// 將其拷貝構(gòu)造和賦值構(gòu)造成為私有函數(shù), 禁止外部拷貝和賦值Singleton(const Singleton &signal);const Singleton &operator=(const Singleton &signal);//解析xml中的內(nèi)容void parseIP(const QDomNode &root);private:// 唯一單實例對象指針static Singleton *g_pSingleton;//存儲IPQVariantList m_ips;
};
源文件:
// 代碼一運(yùn)行就初始化創(chuàng)建實例 ,本身就線程安全
Singleton* Singleton::g_pSingleton = new (std::nothrow) Singleton();Singleton* Singleton::GetInstance()
{return g_pSingleton;
}void Singleton::deleteInstance()
{if (g_pSingleton){delete g_pSingleton;g_pSingleton = nullptr;}
}bool SingleInstance::initalize()
{QString path("目錄");QFile file(path);if(file.exists()){if(file.open(QIODevice::ReadOnly | QIODevice::Truncate)){QString error;QDomDocument document;document.setContent(&file, &error);file.close();if(document.isNull()){qDebug() << QString("文件格式異常:1%").arg(error);return false;}QDomNode root = document.firstChild();parseIP(root);}else{qDebug() << QString("%1:文件不存在,:2%").arg(path).arg(file.errorString());}}else{qDebug() QString("%1:文件不存在!").arg(path);return false;}return !m_ips.isEmpty();
}void Singleton::Print()
{std::cout << "我的實例內(nèi)存地址是:" << this << std::endl;
}Singleton::Singleton()
{std::cout << "構(gòu)造函數(shù)" << std::endl;
}Singleton::~Singleton()
{std::cout << "析構(gòu)函數(shù)" << std::endl;deleteInstance();
}void SingleInstance::parseIP(const QDomNode &root)
{QDomNode startnode = root.nextSibling();QDomNode node = startnode.firstChild();while(!node.isNull()){QVariantMap ips;ips.clear();QDomElement element = node.toElement();ips.insert("ip", element.attribute("ip"));ips.insert("port", element.attribute("port"));ips.insert("multiip", element.attribute("multiip"));}}
main.cpp
if(Singleton::GetInstance()->initalize())
{
...
}
xml說明
<?xml version="1.0" encoding="utf-8"?>XML聲明是XML文檔的第一句
<ips>
<ip ip="xxx" port="xxx" multiip="xxx"/>
</ips>