QList 和std::list的比較


QList

QList<T> 是一個Qt通用容器類。它存儲一序列的值,並且提供基於索引的數據訪問方法和快速的插入和刪除操作。

QList<T>, QLinkedList<T>, 和 QVector<T>提供類似的功能,這里進行幾點概述:

1.     大多數情況下,最好使用QList。它基於索引的API比QLinkedList基於迭代器的API方便。它存儲數據的方式也使得它比QVector存取數據的數度快。而且它在可執行文件中擴展的代碼也比較少。

2.    需要一個真正的鏈表,能保證在中間插入數據的時間復雜度是常量的,用迭代器來存錢元素的,那可以用QLinkedList

3.     如果想容器的元素在相鄰的內存,可以用QVector。

在內部,QList<T>是一個指向T類型的指針數組。如果T本身是一個指針類型或者不大於指針的基本數據類型,或者如果T是一個Qt共享類,QList<T>在直接將元素保持在指針數組中。對於少於一千個元素的鏈表,這樣的數組表示允許在中間快速的插入,而且運行基於索引的存錢方法。此外,prepend() and append() 操作速度也很快,因為QList在其內部數組的兩端預先分配了內存。需要注意的是,對於大於指針的非list 項,每次append 或 insert新的項都需要在堆上分配內存,如果需要這樣的大量的插入和添加操作,這時最好選擇QVector,因為QVector在單一的堆上分配內存。

 

需要注意的是:在list的生命期中,內部數組只有可能變大,不可能縮小。內部數組只能有析構函數釋放或者當用一個list賦值給另外的list時,由賦值函數釋放。

 

為了使QList盡可能高效,它的成員函數不驗證輸入的有效性。除了isEmpty()之外,其他的成員函數都假定list是非空的。使用索引參數的成員函數總是假定索引值是在有效的范圍的。這意味着QList的函數可能調用失敗。如果你在編譯時定義了QT_NO_DEBUG,則將不會捕獲這樣的失敗。如果沒有定義QT_NO_DEBUG, Q_ASSERT() or Q_ASSERT_X() 將捕獲這些失敗彈出適當的信息。

 

為了避免失敗,在調用其他成員函數前調用isEmpty()。如果成員函數用到索引參數,要檢查索引是否在有效的范圍。

和QVector類似,QList也是用的隱式共享。

 

QList<int>integerList;

integerList.push_back(1);

integerList.append(5);

 

//integerList.setSharable(false);

QList<int>List(integerList);

//List= integerList;

//integerList.setSharable(false);

 

cout<<"&List.at(0):"<<&List.at(0)<<endl;

cout<<"&integerList.at(0):"<<&integerList.at(0)<<endl;

 

integerList.setSharable(false);取消注釋之后顯示的地址就不一樣了

 

 

std::list

std::list是一種順序容器,它允許在其中的任何位置進行插入和刪除操作,而且可以雙向迭代。

List容器實現為雙向鏈表,雙向鏈表可以在不同而且不相關的位置進行存儲其元素。其關聯的順序由一個指向前面元素的鏈接和一個指向后面元素的鏈接來保持的。

List類似於forward_list。最主要的不同就是forward_list是單鏈表,所以它只能前向迭代,因此也更小和更高效。

和其他基本的標准容器 (arrayvector and deque)相比,list在插入,提取,移動數據方面更高效,因此在密集的算法中一般都用list,比如排序算法。

和其他順序容器相比,listsand forward_lists最大的缺點就是缺少通過位置直接存取元素的方法;它們也需要額外的內存來保持鏈接的信息。

QList 和std::list比較

構造函數:

QList構造函數:

QList::QList ()

QList::QList ( constQList<T> & other )

 

List構造函數:

C++98版:

explicit list (constallocator_type& alloc = allocator_type());

explicit list (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type());
template <class InputIterator> list (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
list (const list& x);

 

C++11版:

explicit list (const allocator_type& alloc = allocator_type());
explicit list (size_type n); 
list (size_type n, const value_type& val,  const allocator_type& alloc = allocator_type());
template <class InputIterator> list (InputIterator first, InputIterator last,
                                    const allocator_type& alloc = allocator_type());
list (const list& x);
list (const list& x, const allocator_type& alloc);
list (list&& x);
list (list&& x, const allocator_type& alloc);
list (initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());

QList的構造函數只有默認構造函數和拷貝構造函數兩種,std::list的構造函數就比較多了。

 

QList特有的函數:

void QList::append ( const T & value )           在鏈表的末尾插入value

void QList::append ( constQList<T> & value )     在鏈表的末尾插入鏈表value的元素

該函數實際上調用了QList<T> &

operator+= ( const QList<T> & other )

 

bool QList::contains ( const T& value ) const      判斷鏈表是否包含元素value

int QList::count ( const T& value ) const          統計鏈表中值為balue的元素個數

void QList::move ( int from,int to )   把索引為from的值移到索引為to的位置

 

QList<QString> list;

 list << "A" <<"B" << "C" << "D" <<"E" << "F";

 list.move(1, 4);

 // list: ["A", "C","D", "E", "B", "F"]

有關刪除的一些操作:

 

void QList::removeAt (int i )

bool QList::removeOne ( const T & value )

void QList::removeFirst ()

void QList::removeLast ()

T QList::takeAt ( int i )

T QList::takeFirst ()

T QList::takeLast ()

 

與其他類型容器的轉換方式:

QSet<T> QList::toSet () const

std::list<T> QList::toStdList ()const

QVector<T> QList::toVector () const

 

支持的操作符運算:

bool QList::operator!= ( constQList<T> & other ) const

QList<T> QList::operator+ (const QList<T> & other ) const

QList<T> & QList::operator+=( const QList<T> & other )

QList<T> & QList::operator+=( const T & value )

QList<T> &QList::operator<< ( const QList<T> & other )

QList<T> &QList::operator<< ( const T & value )

QList<T> & QList::operator=( const QList<T> & other )

bool QList::operator== ( constQList<T> & other ) const

T & QList::operator[] ( int i )

const T & QList::operator[] ( int i ) const

 

QDataStream & operator<< ( QDataStream & out, const QList<T> & list )

QDataStream & operator>> ( QDataStream & in, QList<T> & list )

 

Std::list特有的函數:

SpliceC++98版:

void splice (iterator position, list& x);
void splice (iterator position, list& x, iterator i);
void splice (iterator position, list& x, iterator first, iterator last);

C++11版:

void splice (const_iterator position, list& x);
void splice (const_iterator position, list&& x);
void splice (const_iterator position, list& x, const_iterator i);
void splice (const_iterator position, list&& x, const_iterator i);
void splice (const_iterator position, list& x, const_iterator first, const_iterator last);
void splice (const_iterator position, list&& x, const_iterator first, const_iterator last);

該函數個功能是:把鏈表x的元素,從x中轉移到該鏈表中,從位置position進行插入。該操作不會調用任何元素的構造函數或析構函數。會同時改變這兩個鏈表的大小。

std::list<int>mylist1, mylist2;

std::list<int>::iteratorit;

for(int i=1; i<=4; ++i)

         mylist1.push_back(i);   

for(int i=1; i<=3; ++i)

         mylist2.push_back(i*10); 

it =mylist1.begin();

++it;                       

mylist1.splice(it, mylist2);

cout<<"mylist1.size():"<<mylist1.size()<<endl;

cout<<"mylist2.size():"<<mylist2.size()<<endl;

it =mylist1.begin();

cout<<"mylist1:";

for(it; it !=mylist1.end(); ++it)

{

         cout<<*it<<" ";

}

cout<<endl;

it =mylist2.begin();

cout<<"mylist2:";

for(it; it !=mylist2.end(); ++it)

{

         cout<<*it<<" \t";

}

 

 

sort操作

void sort();
template <class Compare>
  void sort (Compare comp);
版本1用的是 < 比較操作,版本2用comp 進行比較。這兩個排序進行的是嚴格的弱排序。對與相同的值是穩定的,排序后相對位置不變。元素在容器中進行移動,整個過程不會調用任何構造函數,析構函數或拷貝任何元素。

 

Unique操作:

void unique();
template <class BinaryPredicate>
  void unique (BinaryPredicate binary_pred);
不帶參數的版本1會刪除每一組相同值的除了第一個元素之外的元素,例如,有連續的幾個值為 a  a  a,它會刪除后面的兩個a,值保留第一個a。
版本2用binary_pred作為比較函數,需要注意的是,該函數會為每個比較對調用binary_pred(*i,*(i-1)),如果比較返回true則會從鏈表中刪除i。

boolsame_integral_part (double first, double second)

{

         return ( int(first)==int(second) );

}

structis_near

{

         bool operator() (double first, doublesecond)

         {

                   return(fabs(first-second)<5.0);

         }

};

 

         double mydoubles[]={ 12.15,  2.72, 73.0, 12.77,  3.14,

                   12.77, 73.35, 72.25,15.3,  72.25 };

         std::list<double> mylist(mydoubles,mydoubles+10);

 

         mylist.sort();            

         std::list<double>::iterator it =mylist.begin();

         cout<<"after sort() mylist:";

         int i = 0;

         for (it; it != mylist.end(); ++it, ++i)

         {

                   cout<<*it<<"  ";

                   if (i == 5)

                   {

                            cout<<endl;

                   }

         }

         cout<<endl;

 

         mylist.unique();

         it = mylist.begin();

         cout<<"after unique() mylist:";

         for (it; it != mylist.end(); ++it)

         {

                   cout<<*it<<"  ";

         }

         cout<<endl;

         mylist.unique (same_integral_part);

         it = mylist.begin();

         cout<<"after unique(same_integral_part) mylist :";

         for (it; it != mylist.end(); ++it)

         {

                   cout<<*it<<"  ";

         }

         cout<<endl;

 

         mylist.unique (is_near());         

         it = mylist.begin();

         cout<<"after unique(same_integral_part) mylist :";

         for (it; it != mylist.end(); ++it)

         {

                   cout<<*it<<"  ";

         }

         cout<<endl;

 

 

merge 操作:

C++98版本:
void merge (list& x);
template <class Compare>
  void merge (list& x, Compare comp);
 
C++11版本:
void merge (list& x);
  void merge (list&& x);
template <class Compare>
void merge (list& x, Compare comp);
template <class Compare>
  void merge (list&& x, Compare comp);
該函數把x的元素按適當的順序合並到鏈表中,前提是兩個鏈表都是已經排序了的。
該操作會移除x中的元素插入到鏈表中,和splice一樣,它不會調用構造函數或者析構函數,僅僅是做了轉移而已。
版本2指定了一個比較操作函數,它對元素進行嚴格的弱排序。調用該函數,鏈表必須是已經排序的,對於沒有排序的鏈表,可以用splice。
對於相同的值也是穩定的,其位置和在x中的相對位置一樣。

boolmycomparison (double first, double second)

{

         return ( int(first)<int(second) );

}

 

std::list<double>first, second;

         first.push_back (3.1);

         first.push_back (2.2);

         first.push_back (2.9);

 

         second.push_back (3.7);

         second.push_back (7.1);

         second.push_back (1.4);

 

         first.sort();

         second.sort();

 

         first.merge(second);

         // (second is now empty)

         second.push_back (2.1);

         first.merge(second,mycomparison);

         std::cout << "after mergefirst contains:";

         for (std::list<double>::iteratorit=first.begin(); it!=first.end(); ++it)

                   std::cout << ' '<< *it;

         std::cout << '\n';

         std::cout << "after mergesecond contains  size:"<<second.size()<<endl;

如果我們嘗試把排序的兩句代碼注釋掉,則會彈出失敗的斷言信息。在merge函數中會檢查鏈表是否已經排序。

first.sort();

second.sort();

 

reverse操作:

C++98版本:

void reverse();

C++11版本:

void reverse() noexcept;

該函數對鏈表進行反轉。

std::list<int>mylist;

         for (int i=1; i<10; ++i)

                   mylist.push_back(i);

         std::cout << " beforereverse mylist contains:"<<endl;

         for (std::list<int>::iteratorit=mylist.begin(); it!=mylist.end(); ++it)

                   std::cout << ' '<< *it;

         std::cout << '\n';

         mylist.reverse();

         std::cout << "after reversemylist contains:"<<endl;

         for (std::list<int>::iteratorit=mylist.begin(); it!=mylist.end(); ++it)

                   std::cout << ' '<< *it;

         std::cout << '\n';

 

http://blog.csdn.net/hai200501019/article/details/11747475


免責聲明!

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



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