c++容器学习

容器简介

        c++常用的容器为vector,其是顺序容器。它将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素,这就是顺序容器。顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。容器类共享公共的接口,这使标准库更容易学习,只要学会其中一种类型就能运用另一种类型。

容器的使用

 头文件

 为了定义 一个容器类型的对象,必须先包含相关的头文件,即下列头文件之一:
 #include <vector>
 #include <list>
 #include <deque>

容器的创建

容器副本的创建

        当不使用默认构造函数,而是用其他构造函数初始化顺序容器时,必须指出该容器有多少个元素,并提供这些元素的初值。同时指定元素个数和初值的一个方法是将新创建的容器初始化为一个同类型的已存在容器的副本:

 vector<int> ivec;
 vector<int> ivec2(ivec); // ok: ivec is vector<int>
 list<int> ilist(ivec); // error: ivec is not list<int>
 vector<double> dvec(ivec); // error: ivec holds int not double
将一个容器复制给另一个容器时,类型必须匹配:容器类型和元素类型都必须相同。

容器的初始化

        创建容器时, 我们可以去直接指定容器的大小和容器中任意一个元素来初始化。容器的大小可以是常量,也可以是非常量的表达式。

const list<int>::size_type list_size = 64; 
list<string> slist(list_size, "eh?"); // 64 strings, each is eh?

这段代码表示 slist 含有 64 个元素,每个元素都被初始化为“eh?”字符串。 

容器大小

容器内元素类型的约束

元素类型

C++ 语言中,大多数类型都可用作容器的元素类型。容器元素类型必须满足以下两个约束:
        • 元素类型必须支持赋值运算。
        • 元素类型的对象必须可以复制。

 容器的容器

 定义 vector 类型的容器 lines,其元素为 string 类型的 vector 对象:

vector< vector<string> > lines;

        注意:两个大于号之间有空格,必须这样使用。

迭代器

迭代器的使用

        C++ 语言使用一对迭代器标记迭代器范围(iterator range),这两个迭代器分别指向同一个容器中的两个元素或超出末端的下一位置,通常将它们命名为first 和 last,或 beg 和 end,用于标记容器中的一段元素范围。尽管 last 和 end 这两个名字很常见,但是它们却容易引起误解。其实第二个迭代器从来都不是指向元素范围的最后一个元素,而是指向最后一个元素的下一位置。该范围内的元素包括迭代器 first 指向的元素,以及从 first 开始一直到迭代器 last 指向的位置之前的所有元素。如果两个迭代器相等,则迭代器范围为空。
每种顺序容器都提供了一组有用的类型定义以及以下操作:
        • 在容器中添加元素。
        • 在容器中删除元素。
        • 设置容器大小。
        • (如果有的话)获取容器内的第一个和最后一个元素。

        

常用迭代器运算

除上诉外,vector容器还支持以下运算

 计算vector容器的中心位置:

vector<int>::iterator iter = vec.begin() + vec.size()/2;

 容器定义的类型别名

 

 容器的begin和end操作


元素的插入 

string text_word; 
while (cin >> text_word) 
    container.push_back(text_word);

上面的代码,循环读取string类型的常量,通过使用push_back函数添加到容器container的末尾。

其他添加元素的操作:

 实例:

        将一段元素添加到容器中:

test.insert(test.end(),10,"Anna");

 上面的代码吧10个string类型的常量Anna,添加到test容器的末尾。

        将数组的全部或一部分添加到容器中:

string arr[4] = { "1","2","3","4"};
//将数组全部添加进去
test.insert(test.end(),arr,arr+4);
//吧数组的第3个和第4个元素添加进去
test.insert(test.end(),arr+2,arr+4);

元素的删除 

指定或部分删除

 

while (!ilist.empty()) { 
    process(ilist.front()); // do something with the current top of ilist 
    ilist.pop_front(); // done; remove first element 
}

        这个循环非常简单:使用 front 操作获取要处理的元素,然后调用pop_front 函数从容器 list 中删除该元素。pop_front 和 pop_back 函数的返回值并不是删除的元素值, 而是 void。要获取删除的元素值,则必须在删除元素之前调用notfront 或 back 函数。

        删除一个或一段元素更通用的方法是 erase 操作。该操作有两个版本:删除由一个迭代器指向的单个元素,或删除由一对迭代器标记的一段元素。erase的这两种形式都返回一个迭代器,它指向被删除元素或元素段后面的元素。也就是说,如果元素 j 恰好紧跟在元素 i 后面,则将元素 i 从容器中删除后,删除操作返回指向 j 的迭代器。

全部删除

要删除容器内所有的元素,可以调用 clear 函数,或将 begin 和 end 迭代器传递给 erase 函数。
slist.clear(); // delete all the elements within the container 
slist.erase(slist.begin(), slist.end()); // equivalent

不要储存end操作返回的迭代器

        考虑一个读取容器中每个元素的循环,对读出元素做完处理后,在原始元素后面插入一个新元素。我们希望该循环可以处理每个原始元素,然后使用insert 函数插入新元素,并返回指向刚插入元素的迭代器。在每次插入操作完成后,给返回的迭代器自增 1,以使循环定位在下一个要处理的原始元素。如果我们尝试通过存储 end() 操作返回的迭代器来“优化”该循环,将导致灾难性错误:
vector<int>::iterator first = v.begin(), 
last = v.end(); 
while (first != last) { 
    first = v.insert(first, 42); 
    ++first; // advance first just past the element we added 
}
        在很多实现中,该段代码将导致死循环。问题在于这个程序将 end 操作返回的迭代器值存储在名为 last 的局部变量中。循环体中实现了元素的添加运算,添加元素会使得存储在 last 中的迭代器失效。该迭代器既没有指向容器 v 的元素,也不再指向 v 的超出末端的下一位置。
为了避免存储 end 迭代器,可以在每次做完插入运算后重新计算 end 迭代器值:
while (first != v.end()) { 
 // do some processing 
    first = v.insert(first, 42); // insert new value 
    ++first; // advance first just past the element we added 
}

赋值和swap

与赋值相关的操作符都作用于整个容器。除 swap 操作外,其他操作都可以用 erase 和 insert 操作实现。赋值操作符首先 erases 其左操作数容器中的所有元素,然后将右操作数容器的所有元素 inserts 到左边容器中:
c1 = c2; // replace contents of c1 with a copy of elements in c2 
c1.erase(c1.begin(), c1.end()); // delete all elements in c1 
c1.insert(c1.begin(), c2.begin(), c2.end()); // insert c2
赋值后,左右两边的容器相等:尽管赋值前两个容器的长度可能不相等,但赋值后两个容器都具有右操作数的长度。赋值和 assign 操作使左操作数容器的所有迭代器失效。swap操作则不会使迭代器失效。完成 swap 操作后,尽管被交换元素已经存放在另一容器中,但迭代器仍然指向相同的元素。

 

swap 操作实现交换两个容器内所有元素的功能。要交换的容器的类型必须匹配:操作数必须是相同类型的容器,而且所存储的元素类型也必须相同。调用了 swap 函数后,右操作数原来存储的元素被存放在左操作数中,反之亦然。
vector<string> svec1(10); // vector with 10 elements 
vector<string> svec2(24); // vector with 24 elements 
svec1.swap(svec2);
执行 swap 后,容器 svec1 中存储 24 个 string 类型的元素,而 svec2 则存储 10 个元素。
如有错误,欢迎私信改正!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北木ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值