QList 和std::list的比较

时间:2022-09-01 09:09:39

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;

QList 和std::list的比较

integerList.setSharable(false);取消注释之后显示的地址就不一样了

QList 和std::list的比较

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";

}

QList 和std::list的比较

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;

QList 和std::list的比较

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;

QList 和std::list的比较

如果我们尝试把排序的两句代码注释掉,则会弹出失败的断言信息。在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';

QList 和std::list的比较

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

QList 和std::list的比较的更多相关文章

  1. Qt之Concurrent框架

    简述 QtConcurrent命名空间提供了一个高级API来编写多线程程序,而无需使用低级线程原语,例如:互斥.读写锁.等待条件或信号量.使用QtConcurrent编写的程序使用的线程数量会自动根据 ...

  2. Qt Thread

    Threading Classes (Qt help manual key words) These Qt Core classes provide threading support to appl ...

  3. Understand the Qt containers(有对应表)

    Container classes are one of the cornerstones of object-oriented programming, invaluable tools that ...

  4. 【NX二次开发】NX内部函数,libuifw&period;dll文件中的内部函数

    本文分为两部分:"带参数的函数"和 "带修饰的函数". 浏览这篇博客前请先阅读: [NX二次开发]NX内部函数,查找内部函数的方法 带参数的函数: void U ...

  5. QLinkedList和std&colon;&colon;forward&lowbar;list

    forward_list forward_list是C++11版本才有的.forward_list被实现为单链表,而list是一个双向链表,所以forward_list要比list高效一些.forwa ...

  6. QLinkedList和std&colon;&colon;forward&lowbar;list(都是双向链表,不支持operator&lbrack;&rsqb;,好处可能是插入和删除都比较快)

    forward_list forward_list是C++11版本才有的.forward_list被实现为单链表,而list是一个双向链表,所以forward_list要比list高效一些.forwa ...

  7. 关于QList&lt&semi;T&gt&semi;的内存释放

    当T为指针类型时,List.clear()不能释放其内存,需加上qDeleteAll()函数, //class Person ---> Person(int id_,QString name_) ...

  8. Qt使用std&colon;&colon;sort进行排序

    参考: https://blog.csdn.net/u013346007/article/details/81877755 https://www.linuxidc.com/Linux/2017-01 ...

  9. 4&period;QList

    #include "mainwindow.h" #include <QApplication> #include <QLabel> #include &lt ...

随机推荐

  1. JavaScript中的Array

    Array类型是ECMAScript 用的最多的类型了,ECMAScript中的数组每一项可以保存任何类型的数据,也就是说,数组的第一个项保存字符串,用第二个保存数值,用第三个位置来保存对象.二千数据 ...

  2. javascript中对象函数继承的概念

    什么是函数对象?这个对象既是通常意义上的对象,又可以加上括号直接执行的函数. 产生函数对象的方式有两种:1.通过function关键字产生:var fn = function(){};2.实例化Fun ...

  3. ZOJ 2315

    ---恢复内容开始--- http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1315 这个题目比较难以看懂,我也是看网上的题目意思才 ...

  4. 如何区别PeekMessage&amp&semi;GetMessage SendMessage&amp&semi;PostMessage

    转自http://blog.csdn.net/young0325/article/details/6430664 Peekmessage和Getmessage都是向系统的消息队列中取得消息,不过性质不 ...

  5. 拷贝构造函数,深拷贝,大约delete和default相关业务,explicit&comma;给定初始类,构造函数和析构函数,成员函数和内联函数,关于记忆储存,默认参数,静态功能和正常功能,const功能,朋友

     1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.另外一种初始化的方式是直接在构造方法里面实现初始化. 案比例如以 ...

  6. 如何在mac上搭建sqli-labs

    近期想学习sql注入,但是一来网络上的资料参差不齐,难以系统的学习:二来随着程序员安全意识的提高,这种完全可以避免的注入漏洞越来越少见了,所以难以找一个合适的网站练手,于是乎,sqli-labs这种实 ...

  7. 2017-2018-1 20155201 《信息安全系统设计基础》 pwd命令的实现

    2017-2018-1 20155201 <信息安全系统设计基础> pwd命令的实现 一.对pwd命令的学习 在终端中输入man pwd查看手册中对pwd这一命令的解释: 以绝对路径的方式 ...

  8. Acitivity&lpar;活动&rpar;

    1.首先活动是放在返回栈中. 2.活动的生命周期

  9. EffectiveC&plus;&plus; 第7章 模板与泛型编程

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 7 模版与泛型编程 Templates and Gen ...

  10. windows10环境下VMware14中Ubuntu16&period;04解决如何上网问题

    进入控制面板,网络和Internet,网络连接 点击以太网,查看详细信息 点击属性 --> 共享,允许其他网络-->选择VMnet1 点开虚拟机编辑选项 ,选择 VMNET1 仅主机,其他 ...