C++容器的使用

(未完待修改)

容器所属:容器属于STL中的一部分

容器库是类模板与算法的汇集,允许程序员简单地访问常见数据结构,例如队列、链表和栈。有三类容器——顺序容器、关联容器和无序关联容器——每种都被设计为支持不同组的操作。

容器管理为其元素分配的存储空间,并提供直接或间接地通过迭代器(拥有类似指针属性的对象)访问它们的函数。

大多数容器拥有至少几个常见的成员函数,并共享功能。特定应用的最佳容器不仅依赖于提供的功能,还依赖于对于不同工作量的效率。

可分为三大类:

1、序列式容器

    array、vector、deque、list、forward_list

2、关联式容器

    set/multiset、map/multimap

3、无需容器

   unordered_set/unordered_multiset、unordered_map/unordered_multimap

 

容器提供的函数:

Sequence containers(序列式容器)

Headers<array><vector><deque><forward_list><list>
Membersarrayvectordequeforward_listlist
 constructorimplicitvectordequeforward_listlist
destructorimplicit~vector~deque~forward_list~list
operator=implicitoperator=operator=operator=operator=
iteratorsbeginbeginbeginbeginbegin
before_begin
begin
endendendendendend
rbeginrbeginrbeginrbegin rbegin
rendrendrendrend rend
const iteratorscbegincbegincbegincbegincbegin
cbefore_begin
cbegin
cendcendcendcendcendcend
crbegincrbegincrbegincrbegin crbegin
crendcrendcrendcrend crend
capacitysizesizesizesize size
max_sizemax_sizemax_sizemax_sizemax_sizemax_size
emptyemptyemptyemptyemptyempty
resize resizeresizeresizeresize
shrink_to_fit shrink_to_fitshrink_to_fit  
capacity capacity   
reserve reserve   
element accessfrontfrontfrontfrontfrontfront
backbackbackback back
operator[]operator[]operator[]operator[]  
atatatat  
modifiersassign assignassignassignassign
emplace emplaceemplaceemplace_afteremplace
insert insertinsertinsert_afterinsert
erase eraseeraseerase_aftererase
emplace_back emplace_backemplace_back emplace_back
push_back push_backpush_back push_back
pop_back pop_backpop_back pop_back
emplace_front  emplace_frontemplace_frontemplace_front
push_front  push_frontpush_frontpush_front
pop_front  pop_frontpop_frontpop_front
clear clearclearclearclear
swapswapswapswapswapswap
list operationssplice   splice_aftersplice
remove   removeremove
remove_if   remove_ifremove_if
unique   uniqueunique
merge   mergemerge
sort   sortsort
reverse   reversereverse
observersget_allocator get_allocatorget_allocatorget_allocatorget_allocator
datadatadata   

 

Associative containers(关联式容器)

 

Headers<set><map><unordered_set><unordered_map>
Memberssetmultisetmapmultimapunordered_setunordered_multisetunordered_mapunordered_multimap
 constructorsetmultisetmapmultimapunordered_setunordered_multisetunordered_mapunordered_multimap
destructor~set~multiset~map~multimap~unordered_set~unordered_multiset~unordered_map~unordered_multimap
assignmentoperator=operator=operator=operator=operator=operator=operator=operator=
iteratorsbeginbeginbeginbeginbeginbeginbeginbeginbegin
endendendendendendendendend
rbeginrbeginrbeginrbeginrbegin    
rendrendrendrendrend    
const iteratorscbegincbegincbegincbegincbegincbegincbegincbegincbegin
cendcendcendcendcendcendcendcendcend
crbegincrbegincrbegincrbegincrbegin    
crendcrendcrendcrendcrend    
capacitysizesizesizesizesizesizesizesizesize
max_sizemax_sizemax_sizemax_sizemax_sizemax_sizemax_sizemax_sizemax_size
emptyemptyemptyemptyemptyemptyemptyemptyempty
reserve    reservereservereservereserve
element accessat  at   at 
operator[]  operator[]   operator[] 
modifiersemplaceemplaceemplaceemplaceemplaceemplaceemplaceemplaceemplace
emplace_hintemplace_hintemplace_hintemplace_hintemplace_hintemplace_hintemplace_hintemplace_hintemplace_hint
insertinsertinsertinsertinsertinsertinsertinsertinsert
eraseeraseeraseeraseeraseeraseeraseeraseerase
clearclearclearclearclearclearclearclearclear
swapswapswapswapswapswapswapswapswap
operationscountcountcountcountcountcountcountcountcount
findfindfindfindfindfindfindfindfind
equal_rangeequal_rangeequal_rangeequal_rangeequal_rangeequal_rangeequal_rangeequal_rangeequal_range
lower_boundlower_boundlower_boundlower_boundlower_bound    
upper_boundupper_boundupper_boundupper_boundupper_bound    
observersget_allocatorget_allocatorget_allocatorget_allocatorget_allocatorget_allocatorget_allocatorget_allocatorget_allocator
key_compkey_compkey_compkey_compkey_comp    
value_compvalue_compvalue_compvalue_compvalue_comp    
key_eq    key_eqkey_eqkey_eqkey_eq
hash_function    hash_functionhash_functionhash_functionhash_function
bucketsbucket    bucketbucketbucketbucket
bucket_count    bucket_countbucket_countbucket_countbucket_count
bucket_size    bucket_sizebucket_sizebucket_sizebucket_size
max_bucket_count    max_bucket_countmax_bucket_countmax_bucket_countmax_bucket_count
hash policyrehash    rehashrehashrehashrehash
load_factor    load_factorload_factorload_factorload_factor
max_load_factor    max_load_factormax_load_factormax_load_factormax_load_factor

 

容器数据结构解析:

vector:采用的数据结构非常简单,线性连续空间。

vector是动态空间,随着数据的加入,内部机制会扩充空间来容纳新元素,vector的实现技术,关键在于对其大小的控制以及重新配置时的数据移动效率。

所谓动态增加大小,并不是在原有的空间之后连接新的空间,而是以原来大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,然后在原内容之后构造新元素,并释放原空间。

在C++11之前缩减vector容量的小窍门,两个容器交换内容,两者的容量也会交换,虽然保留了元素,但是缩减了容量。

C++11提供了shrink_to_fit()函数。

注意点: vector的任何操作一旦引起空间重新配置,指向原vector的所有迭代器都会失效,务必小心。

 

list:不仅仅是一个双向链表,而且是一个环状双向链表,只需一个指针,便可遍历一个整个链表。

list在空间上是不连续的,每次新增一个元素或者删除一个元素,就配置一个或者释放一个元素空间,空间运用精准一点不浪费,对元素的插入或删除永远是常数时间。

 

deque:是一种双向开口的连续空间(逻辑上),可以再头部尾部进行插入和删除操作

deque是由一段一段的连续空间组成,通过一个所谓的map来维护空间的连续性,map是一块连续的空间每个元素都是一个指针,指向一块较大的连续性空间,此空间是deque真正存储数据的空间。

在deque的中间插入删除元素都会导致迭代器的失效,deque的内存冲分配优于vector,不必重新分配时复制所有元素。

 

set/multiset:会根据特定规则准则,自动将元素排序,通常以红黑树实现。

 

 

map/multimap:会根据key来自动排序,通过红黑树来实现

map提供了下标操作符,支持元素的直接访问,优点是方便的添加元素,缺点容易误添加元素。

如:cout<<mymap['hello'];  如果不存在hello那么此时自动添加了一个新的元素进来。

 

unordered_set/unordered_multiset、unordered_map/unordered_multimap:以hashtable来实现。

 

 

各容器的使用时机:

 

迭代器非法化:

只读方法决不非法化迭代器或引用。修改容器内容的方法可能非法化迭代器和/或引用,总结于此表格。

类别容器插入后……擦除后……条件
迭代器合法?引用合法?迭代器合法?引用合法?
顺序容器arrayN/AN/A 
vectorN/A插入更改容量
被修改元素前
于被修改元素或其后
deque是,除了被擦除元素修改首或尾元素
仅修改中部
list是,除了被擦除元素 
forward_list是,除了被擦除元素 
关联容器set

multiset

map

multimap

是,除了被擦除元素 
无序关联容器unordered_set

unordered_multiset

unordered_map

unordered_multimap

N/A插入导致重哈希
是,除了被擦除元素无重哈希

此处插入指代任何添加一或多个元素到容器的方法,而擦除指代任何从容器移除一或多个元素的方法。

尾后迭代器需要特别留意。通常像指向未被擦除元素的正常迭代器一般非法化此迭代器。故 std::set::end 决不被非法化, std::unordered_set::end 仅在重哈希时被非法化, std::vector::end 始终被非法化(因为它始终出现在被修改元素后),以此类推。

有一个例外:删除 std::deque 末元素的擦除操作非法化尾后迭代器,尽管它不是容器的被擦除元素(或者说根本不是元素)。与 std::deque 迭代器的通用规则结合后,最终结果是非法化 std::deque::end 的唯一修改操作是删除首元素,而非末元素的擦除。

线程安全

  1. 能同时在不同容器上由不同线程调用所有容器函数。更广泛而言, C++ 标准库函数不读取能通过其他线程访问的对象,除非这些对象能直接或间接地经由函数参数,包含 this 指针访问。

  2. 能同时在同一容器上由不同线程调用 const 成员函数。而且,成员函数 begin() 、 end()rbegin() 、 rend() 、 front() 、 back() 、 data() 、 find() 、 lower_bound() 、 upper_bound() 、 equal_range() 、 at() 和除了关联容器中的 operator[] 对于线程安全的目标表现如同 const (即它们亦能同时在同一容器上由不同线程调用)。更广泛而言, C++ 标准库函数不修改对象,除非这些对象能直接或间接地经由函数参数,包含 this 指针访问。

  3. 同一容器中不同元素能由不同线程同时修改,除了 std::vector<bool> 的元素(例如, std::future 对象的 vector 能从多个线程接收值)。

  4. 迭代器操作(例如自增迭代器)读但不修改底层容器,而且能与同一容器上的其他迭代器操作同时由 const 成员函数执行。非法化任何迭代器的容器操作修改容器,且不能与任何在既存迭代器上的操作同时执行,即使这些迭代器未被非法化。

  5. 同一容器上的元素可以同时由不指定为访问这些元素的函数修改。更广泛而言, C++ 标准库函数不间接读取能从其参数访问的对象(包含容器的其他对象),除非其规定要求如此。

  6. 任何情况下,容器操作(还有算法,或其他 C++ 标准库函数)可于内部并行化,只要不更改用户可见的结果(例如 std::transform 可并行化,但指定了按顺序观览序列的每个元素的 std::for_each 不行)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值