1.STL與數據結構
STL是C++裏最常用的容器(但不是最好的容器)。很多人在計算機學習階段,對計算機的數據結構課程是一塌糊塗的;這種一塌糊塗的感覺,甚至伴隨着很多計算機軟件工程師的長期的職業週期。當然,這其實並不能夠完全怪計算機學習者,相當一部分原因是中國大學的計算機學習的教材把明明很簡單的事物弄成非常複雜的事物。大學的數據結構教材,一般是張乃孝的《算法與數據結構》和嚴蔚敏《數據結構》;這兩本教材楞是把很簡單的事物搞的複雜化,以至很多人想起數據結構依然心有餘悸。
比較好的教材是侯捷先生的《STL詳解》,或者 馬克·艾倫·維斯 的數據結構教材。這些書的好處是:用數據結構的原理講透,同時讓學習者理解這些數據結構在軟件開發中的作用。
當然,我的總結是:數據結構這門課程的作用是,告訴計算機專業者不同數據結構的存在形式、用法和事件複雜度,從而讓計算機從業者在設計程序的時候,能夠具有設計思想。
STL是C++提供的一套數據結構和算法,這套數據結構和算法,包含常見的數據結構,並具有很多通用算法。這種數據結構,帶來了極大便利:
1)讓軟件工程師不再重複發明輪子,而更專注與軟件產品本身;
2)讓C++工程師不再過分考慮容器的內存分配和釋放問題;
3)容器配合迭代器,創造了一種泛型和迭代編程模型,讓軟件工程師開始迭代模型的開發。
其他語言,也紛紛造出自己的容器“輪子”,大量方便工程師學習的語言飛速發展。
但STL本身,卻又很大不利性。比如,內存分配一次分配過下,導致大量出入數據的時候,內存重新分配頻繁,造成效率不高;STL本身,不具有太多的錯誤發現性,導致容器出錯而不易被發現。
2.QT對STL的升級改造
C++98之後,C++11對STL進行了升級改造,一定程度上彌補了STL的不足。如STL的C++11裏的容器,增加了HashMap,彌補了原來STL的Map沒有采用Hash這一快速數據結構的不足。
而QT自己更是自己打造了一套自己的容器。彌補了STL容器的不足。
QT的容器的好處體現在:增加了很多斷言活範圍特性,讓C++的錯誤更容易暴露。
下面,將會以STL的vector和QT QVector爲例,介紹發現的QT容器的便利性。
3.STL vector 與 QT QVector
STL的vector一開始分配空間,但STL的vector發生訪問越界(如果vector的大小不是爲0)的時候,並不會出錯。STL的vector的[]操作符訪問實現如下:
// element access
/**
* @brief Subscript access to the data contained in the %vector.
* @param __n The index of the element for which data should be
* accessed.
* @return Read/write reference to data.
*
* This operator allows for easy, array-style, data access.
* Note that data access with this operator is unchecked and
* out_of_range lookups are not defined. (For checked lookups
* see at().)
*/
reference
operator[](size_type __n) _GLIBCXX_NOEXCEPT
{ return *(this->_M_impl._M_start + __n); }
通過*(this->_M_impl._M_start + __n)可知,如果this指針存在,_M_impl._M_start存在,該操作符並不一定出錯。
而QT的QVector則對[]操作符的使用如下:
template <typename T>
inline T &QVector<T>::operator[](int i)
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
return data()[i]; }
可見,如果訪問的元素超過QVector的方位,QVector的斷言會拋出一個錯誤。
4.樣例
爲比較兩者的不同,可以實現一個樣例:
#include<vector>
#include<QVector>
#include <QCoreApplication>
#include <QDebug>
using std::vector;
int main(int argc, char *argv[])
{
vector<int> vTest;
vTest.push_back(1);
qDebug()<<vTest.capacity();
int iTest;
for(int i = 0; i < 256; i++)
{
iTest = vTest[i];
}
QVector<int> qvecTest;
qvecTest.push_back(1);
iTest = qvecTest[0];
qDebug()<<qvecTest.capacity();
for(int i = 0; i < 256; i++)
{
iTest = qvecTest[i];
}
QCoreApplication a(argc, argv);
return a.exec();
}
運行結果如下:
可以得知:
1)STL的vector最開始分配的空間是1個,而QVector開始分配的空間爲4個(可見QT在空間分配上的優化);
2)STL的vector發生超過容量本身的訪問,並不一定失敗(因爲內存可能足夠大並存在),而QVector則發生了斷言錯誤。而顯然,第二種處理方式會更好。而第一種可能會造成莫名其妙的錯誤,尤其是當工程師忘記vector的範圍,而vector本身並不出錯的時候。
5.啓示
顯然,QT的容器基於STL進行了升級。如果有類似於QT的容器之類的容器,優先選擇更好的容器;而如果使用STL,要知道STL這種特點,並避免這類事情發生。