没有找到您需要的,用Google搜索一下

2009年4月3日星期五

C++ Primer读书笔记 9章

文章来源http://xuexi88.blogspot.com/


问题:如果一个容器的元素是自定义类型,并且没有默认构造函数,并且构造函数不止一个参数,如果使用
vector<Foo>(n,t)初始化?
第九章 容器
1.顺序容器中,元素顺序与元素进入容器顺序有关,于元素值无关。
2.标准库定义了三种顺序容器: Vector List Deque(双端队列)
3.标准库提供了三种适配器 adaptor 是根据原始容器类型所提供的 操作,接口
包括 stack queue(先进先出) priority_queue
4.容器只是定义了少量的操作,大多数额外的操作由算法库提供。
5.容器的操作集合分以下层次
.一些操作适用于所有容器操作
.另外一些使用于顺序或关联容器
.还有一些操作只适用于顺序或关联容器的一个子集。
6.三种头文件: vector list queue
7.容器本质是类型的模板。
8.容器类型的构造函数
C<T> c; 采用默认构造,适用于所有容器
C c(c2);创建c2的副本c,要求: c c2 要容器相同,元素类型相同。使用所有容器。
C c(b,e) 创建c,元素是迭代器b e标示范围内的所有元素。不要求迭代器类型相同,也不要求元素类型完全相同,但至少可以默认转换。迭代器标示了,要复制的第一个元素和最后一个元素。适用于所有容器。注意此方式,没有要求两种容器类型必须相同。即可以用vector 的迭代器来初始化List.
C c(n,t) 用n个值为t的元素创建c,t的类型要符合该容器,或者可转换,仅顺序容器。
C c(n) 创建n个值初始化元素的c仅顺序容器。
9.注意:指针就是迭代器??可以适用一段指针来初始化容器?P266
10.再解值初始化:如果是内置类型,初始化0.如果是类,默认构造。如果没有构造,必须显示给予初始化式。
11.容器元素类型的约束:必须是可赋值的类型,必须可以复制。
12.引用类型不支持一般意义的赋值运算,因此没有引用类型的容器。
13.出输入输出标准库类型以及auto_ptr类型之外,所有标准库类型都是有效的容器元素类型。容器本身也算。(IO类型不支持复制赋值。)
14.如果类Foo没有默认构造函数,但有一个带int参数的构造函数可以这样初始化
vector<Foo> var(10,1) 1为传递给Foo构造函数的参数,此为对类类型提供显示的初始化式
容器的容器
1.注意定义容器的容器时,要如下使用括号
vector< vector<string> > lines;
2.每种容器类型都提供若干种共同工作的迭代器类型。iterator const_iterator 大概这意思
3.与容器类型一样,所有迭代器都有相同的接口:如果某种迭代器支持某种操作,那么支持这种操作的其他迭代器也以相同的方式来支持这种操作。比如所有迭代器都支持以解引用运算从容器中读入一个元素。还如:加减移动迭代器。
4.迭代器所支持的常见操作:
*iter 解引用
iter->mem 解引用,并获得指定元素中的mem成员
++iter iter++ --iter iter--移动
iter1==iter2 iter1!=iter2 当两个指向同个元素,或都是末端,则同。
5.vector 和deque的迭代器提供两种重要的运算:
算术运算和关系运算
iter+n iter-n iter1+=iter2 iter1-=iter2 iter1-iter2
> >= < <=
6关系操作符只适用于vector 和 deque 因为只有这两种容器为其元素提供快速随即访问。
7.添加删除容器元素,会引起悬垂指针问题。
8.顺序容器定义的操作:
添加删除元素
设置容器大小
获取容器第一个和最后一个元素。
9.容器定义的类型别名:
size_type
iterator
const_iterator 只读迭代器
reverse_iterator 逆序迭代器
const_reverse_iterator 逆序只读迭代器
difference_type 两个迭代器差值的有符号整形
value_type 元素类型等效
reference 元素的左值类型,是value_type&的同义词
const_reference 常量左值类型 等效于const value_type&
10.list<string>::iterator iter; iterator 是在::左边的作用域内定义的。是存放string类型元素的List类的成员。
11. c.rbegin()指向最后一个元素,c.rend()指向第一个元素的前面的位置。
12.上述每个操作都返回两个版本: const和非const,如果容器不是const容器,返回iterator 或reversea_iterator类型的迭代器。反之则返回const_iterator const_reverse_iterator类型。
13.所有容器都支持push_back操作。末尾增加一个新元素,长度增长1。
push_front 仅用于在list deque
14.顺序容器增添元素的操作:
c.push_back(t) 在末尾增加
c.push_front(t) 在元素的前边添加 只适用于list 和deque容器
c.insert(p,t)在p的前边加个t
c.insert(p,n,t)
c.insert(p,b,e)
15.关键概念
容器中添加元素时,都是将值复制到容器里。
16.一个等效与push_front的函数
list<string> lst;
list<string>::iterator iter = lst.begin();
while(cin>>word)
iter=lst.insert(iter,word);
17插入一段元素: 迭代器与数组指针的交叉
string sarry[4]={"abc","def","ghi","jkl"};
slist.insert(slist.end(),sarray,sarray+4);//数组的最末元素的下一个。
list<string>::iterator slist_iter=slist.begin();
slist.insert(slist_iter,sarray+2,sarray+4);
18.迭代器如何失效?举个例子试试。程序必须确保容器元素变化后迭代器得到更新。
19.在容器中任何位置插入任何元素,都使存储end()的迭代器失效。所以不要存储end()的返回值。
20.难道这就不是死循环了吗?
while(first!=v.end)
{
first=v.insert(first,42);
++first;
}

关系操作符:
1.容器使用关系操作符比较必须保证:容器类型相同,元素类型相同。
2.容器的比较使用元素类型定义的同一个关系操作符。如果元素不支持使用某种关系操作符那它的容器也不能使用。 c++语言只允许两个容器做其元素类型定义的关系运算。
3.关系比较的规则
长度,元素都同则同
长度不同,较短的一个与较长一个对应元素都一样,则短的小。
如果2也不是,比较第一个不相同的元素。

容器大小操作
1.容器类型顺序操作
c.size() 返回容器内元素个数,类型: c::size_type
c.max_size() 返回容器c可容纳元素的个数
c.empty() 返回是否为空
c.resize(n) 使其能容纳n个元素,如果n<c.size() 就将多余元素删除,否则,添加值初始化的新元素。
c.resize(n,t) 新填的元素用t初始化
2.resize 会使元素迭代器失效
访问元素
1.顺序容器访问元素操作
c.back() 最后一个元素的引用
c.front 第一个元素的引用
如果容器为空,这两个操作会返回未定义的结果。
c[n] 返回下表是n的元素的引用。注意是引用。。。如果n不在范围内,操作未定义。
c.at[n] 同上,但是在越界时抛出out_of_range异常
下标访问仅用于 vector 和 deque两个容器。

删除元素的操作
1.删除操作:
c.erase(p) 删除迭代器p的元素,返回下一个,如果p就是end(),该操作未定义
c.erase(b,e) 如果e就是end() 返回的还是end()
c.clear()
c.pop_back() 删除最后一个,如果空容器,操作未定义 返回void
c.pop_front() 删除第一个,仅用于 list deque
容器复制操作
1. c1=c2 删除c1所有,然后用c2元素复制,要求容器类型元素类型都相同
c1.swap(c2)同样类型要相同,速度要比c2复制到c1快。
c.assign(b,e)重设c的元素,b,e不能是c中的迭代器
c.assign(n,t)用t重设c
2.assign可以用于不同容器类型,不同元素类型,好像使用迭代器复制的都是这样。
3.swap感觉就像交换了两个容器的名称一样,其他的全没变。

vector容器的自增长
1.vector 中的元素是连续存储的。
2.vector的增长效率比list和deque效率更高
3.capacity 与reserve 当vector 不得不重新分配空间时,capacity 会翻倍。

容器的选用
1.元素是否连续存放影响:在中间位置添加删除元素的代价,和执行元素随即访问的代价。
2.deque大概也是连续存放因为: vector deque提供对元素的快速随即访问,而list不是连续。但是随机访问比较慢。
3.从deque的两端插入元素会很快,但是vector 仅仅是后边。在deque首尾添加不会使迭代器失效,但是在其他位置添删会使所以迭代器失效,大概迭代器就是个和位置相关的指针。
4.要理解为什么vector 和deque可以快速高效的随机访问,而list不行。见p288
5.容器选择的规则:
如果要随机,就是vector deque 如果要在中间插入,用List,如果首尾插入,用deque.
如果仅在读入时需要在中间插入,然后要随机访问,则先用list读入,然后拷贝到vector中。
6.如果无法确定应该使用哪种容器,则只使用vector list都提供的操作,使用迭代器不用下标。

字符容器
1.可将string 视为字符容器。除了一些特殊操作,string 与vector提供相同的操作。不同的是:不能用栈操作,front back pop_back.
2.P289: string支持的操作。
3.string 构造总结:
string s1;空串
string s2(s1);初始化s1的副本。
string s3("aaa"),初始化为一个字符串字面值的副本。
string s4(n,'c')初始化为c的n个副本
string s5(s3.begin(),s3.begin()+s3.size()/2)用两个迭代器
string s6(cp,n); cp所指向数组的前n个元素
string s7(s2,pos2) 用字符串s2,下表pos2开始的字符初始化。
string s8(s2,pos2,len2) 从pos2开始,取len2个长度。如果要求长度超出,有多少复制多少。

char *p="hahaha";
char c_array[]="world!!!!";
char no_null={'H','i'};
string s1(p);用一个指向c style字符串的指针初始化。
string s2(c_array,5);//OK
string s3(c_array+5,4); //OK
string s4(no_null); //error
string s5(no_null,2); //OK
要用c style字符串初始化string ,要么指定位数,要么末尾要有\0.
4.
string 的操作总结:
s.empty();
s.size();
s[n];
s1+s2;
s1=s2;
v1==v2;
< <= > >= !=
与容器共有的操作:
s.insert(p,t);
s.insert(p,n,t);
s.insert(p,b,e);
s.assign(b,e);
s.assign(n,t);
s.erase(p);
s.erase(b,e);
string 特有的操作:
s.insert(pos,n,c);在下标 pos值钱插入。
s.insert(pos,s2);下表pos值钱插入s2的副本。
s.insert(pos,s2,pos2,len);下标pos之前插入s2中pos2开始的长度为len的副本。
s.insert(pos,cp,len);下标pos前插入数组cp的len个元素。???如果超出长度,又没有\0会如何。
s.insert(pos,cp);pos前插入cp指向的以空字符结尾的字符串副本。
s.assign(s2);
s.assign(s2,pos,len);
s.assign(cp,len);
s.assign(cp);
s.erase(pos,len);删除从pos开始的len个元素。
只适用于容器类型的操作
s.substr(pos,n);
s.substr(pos);到末尾了
s.substr();返回本身。
string类型提供了6个append重载函数的版本,和10个replace版本(不是12个吗。)
s.append(args);
s.replace(pos,len,args);
s.replace(b,e,args);
参数args
s2
s2,pos2,len2
cp
cp,len2
n,c
b2,e2
string类型的查找操作
s.find(args); 完整匹配
s.rfind(args);
s.find_first_of(args); 包含匹配
s.find_last_of(args);
s.find_first_no_of(args);
s.find_last_not_of(args);
查找操作的args
c,pos 从pos开始查找字符 c pos默认值为0
s2,pos 从s的pos2找s2
cp,pos
cp,pos,n 从pos开始找cp中的前n个。
string 的比较对象操作
关系操作符比较:
如果两个string长度不同,且短的完全匹配长的开始部分。则短的小,否则逐字匹配,区分大小写。
比较操作:
s.compare(s2)
s.compare(pos1,n1,s2);从pos1开始的n1个字符与s2比较
s.compare(pos1,n1,s1,pos2,n2);
s.compare(cp);
s.compare(pos1,n1,cp);
s.compare(pos1,n1,cp,n2);这个不指定cp的开始位置。
整数s1大,,负数 s1小, 0 相等。

容器适配器:
1.适配器是标准库中的通用概念,包括容器适配器,迭代器适配器,函数适配器。
2.适配器通用的操作和类型
3.两个头文件:stack queue
4.默认stack 和 queue都是基于deque实现。priority_queue基于vector容器实现
5.通过将一个顺序容器指定为适配器的第二个类型实参,可以覆盖其关联的容器类型。
如:stack<string ,vector<string>> str_stk;
6.queue适配器要求其关联的容器支持push_front 运算,因此只能建立在list上不能建立在vector容器上
与之相反,priotity_queue要求能提供随机访问,可以建立在vector deque上不能建立在list容器上。
栈适配器
1.栈容器适配器支持的操作:
s.empty() 如果空返回true
s.size() 返回栈中元素的个数
s.pop()删除栈顶元素,不返回其值。
s.top()返回栈顶元素
s.push() 栈顶压入新元素
队列
1. queue:先进先出队列
priority_queue:优先级队列
2.队列和优先级队列支持的操作
q.empty()
q.size()
q.pop()
q.front()只适用于队列
q.back()只适用于队列
q.top()返回优先级最高的队列 只适用于优先级队列
q.push()


文章来源http://xuexi88.blogspot.com/

0 评论:

发表评论