今天看同事寫的代碼裡有如下的代碼:
for(int i =0;i < map_T.count(); i++)
{
T * t = map_T.value(map_T.keys().at(i));
}
我評論到這樣速度太慢(其實內容不多,用什麼方式遍歷用戶是感覺不到的)應該用迭代器遍歷,結果引起激烈的討論,同時還討論到了鏈表的遍歷方法,並且還拿群裡給出的數據說明用“下標”遍歷鏈表比用迭代器快。
於是我自己也寫了段代碼進行測試(測試代碼很easy,就不粘貼了),結果顯示,map用key去遍歷value的速度比直接用迭代器慢了十倍多,因為使用key去訪問value時,每一次訪問都會引起二分查找,而用迭代器訪問時,時間復雜度為O(1)(我沒去分析源碼,猜的),必然要比用key去一個個索引value快。
而在測試鏈表時,我突然發現STL中的list根本就沒提供下標訪問函數,原因是用下標訪問的最壞時間復雜度太大,例如當鏈表長度很大時,要用下標去訪問中間的一個結點時,必然要經過很多步的間接訪問。
說出了這個情況後,同事說Qt中提供的QList有提供QList<T>::at(int)函數,用於下標訪問,並且速度比迭代器快,我不服,不服跑個分呗,於是又進行測試,結果卻是,用at函數遍歷比用迭代器快了近一倍,不解啊,於是就去分析QList的源代碼了,結果發現下面這段代碼:
struct Q_CORE_EXPORT QListData {
struct Data {
QtPrivate::RefCount ref;
int alloc, begin, end;
void *array[1];
};
Data *d;
inline void **at(int i) const { return d->array + d->begin + i; }
inline void **begin() const { return d->array + d->begin; }
inline void **end() const { return d->array + d->end; }
/// .........................
};
算是好好上了一課。
估計Qt是為了提高速度,使用了連續內存,提高了隨機訪問的速度,看來不能拿其它庫和自己相對熟悉點的STL比啊,畢竟有些庫是做了優化的,不能固化自己的知識。