在本章中,简要介绍了string、vector、bitset 三个标准库类型。
1、using声明
1)在引用标准库中名字时,需要加上作用域操作符,例如 std::cin 。
2)使用 using 声明可以更简洁得使用命名空间,例如只需在文件开头添加using std::cin ,则在下面可以直接引用名字,而不需要再引用该名字的命名空间。
3)在头文件中,必须总是使用完全限定的标准库名字,即上面的第一种情况。因为头文件的内容会被预处理器复制到程序中,如果头文件中放置了using声明,就相当于包含该头文件的每个程序中都放置了同一个using声明,不论该程序是否需要using声明。
2、string类型的初始化有以下四种方法
1)string s1; | 默认构造函数,s1为空串 |
2)string s2(s1); | 将s2初始化为s1的一个副本 |
3)string s3("value"); | 将s3初始化为一个字符串字面值副本 |
4)string s4(n, 'c'); | 将s4初始化为字符'c'的n个副本 |
3、字符串字面值与标准库string类型不是同一种类型!
4、使用cin>>s;来读入string类型,
1)读取并忽略开头所有的空白字符(如空格、换行符、制表符。)
2)读取字符直至再次遇到空白字符,读取终止,该空白符仍留在输入流中。
5、使用 getline(cin, s); 读取一整行的字符串,从输入流的下一行开始读取,并保存到string中,但不包括换行符,读取时也不忽略行开头的换行符。
6、由于getline函数返回时丢弃换行符,换行符将不会存储在string对象中。
7、任何存储string的size操作结果的变量必须为 string::size_type 类型。特别重要的事,不要把size的返回值赋给一个int 变量。因为 string::size_type 是unsigned型,它所能存储的长度是int型的两倍,且int型在有些机器上所表示范围太小,极易发生溢出。
8、string对象的大小比较:
1)如果两个string对象长度不同,且短的string对象与长的string对象的前面部分相匹配,则短的string对象小于长的string对象。
2)如果两个string对象的字符不同,则比较第一个不匹配的字符。
例: string a = "Hello", b ="Hello World", c ="Hiya";
则 a<b<c;
9、string a, b="hello"; a = b; 赋值过程:
1)先把a占用的相关内存释放掉,
2)分配给a足够存放b副本的内存空间,
3)把b中的所有字符复制到新分配的内存空间。
10、当string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型的。
例如: string a = "hello";
string b = a + " world"; // 对
string c = "hello" + "world"; // 错
string d = a + " world " + "bye" ; // 对
string e = " world " + "bye" + a; // 错 (自左向右运算)
11、任何可产生整型值的表达式都可用作下表操作符的索引,但索引的实际数据类型却是unsigned 类型string::size_type,所以索引最好也选择string::size_type类型。
12、在使用下标索引string对象时,必须保证索引值“在上下界范围内”。标准库不要求检查索引值,所以索引的下标越界是没有定义的,这样往往会导致严重的运行时错误。
13、string对象中字符处理,cctype定义的函数:
isalnum() | 是否为字母或数字 |
isalpha() | 是否为字母 |
iscntrl() | 是否为控制字符 |
isdigit() | 是否为数字 |
isgraph() | 是否为除空格之外的打印字符 |
islower() | 是否为小写 |
isprint() | 是否为可打印字符,包括空格 |
ispunct() | 是否为标点符号 |
isspace() | 是否为标准空白字符,如空格、进纸、换行符、回车、水平或垂直制表符 |
isupper() | 是否为大写 |
isxdigit() | 是否为组成16进制数的符号或数字 |
tolower() | 转换为小写 |
toupper() | 转换为大写 |
14、vector不是数据类型,而只是一个类模板,可用来定义任意多种数据类型。它是同一种类型对象的集合。因此, vector<int> 和 vector<string> 都是数据类型。
15、vector对象的四种初始化方法:
1)vector<T> v1; | vector保存类型为T的对象。默认构造函数,v1为空。 |
2)vector<T> v2(v1); | v2是v1的一个副本。 |
3)vector<T> v3(n, i); | v3包含n个值为i的元素。 |
4)vector<T> v4(n); | v4含有值初始化的元素的n个副本。 |
16、vector对象(以及其他标准库容器对象)的重要属性就在于可以在运行时高效地添加元素。因为vector增长的效率高,当元素值已知时,最好是通过动态地向它添加元素来让它增长。
17、vector对象中如果没有指定元素的初始化式,标准库将会提供一个元素初始值进行值的初始化,有以下三种情况:
1)如果vector保存内置类型(如int型)的元素,那么标准库将用0值初始化。
2)如果vector保存的是含有构造函数的类类型(如string)的元素,标准库将用该类型的默认构造函数创建元素初始化。
3)如果元素类型是没有定义任何构造函数的类类型,标准库仍产生一个带初始值的对象,这个对象的每个成员进行了值初始化。(未知)
18、安全的泛型编程
1)习惯于优先选用 != 而不是 < 来编写循环判断条件。
2)调用size成员函数而不保存它返回的值,我们倾向于在每次循环中测试size的当前值,而不是进入循环前存储其副本。像size这样的小库函数几乎都定义为内联函数,所以每次循环过程中调用它的运行时代价是比较小的。
19、因为只有少数容器支持下标操作,而迭代器(iterator)对所有容器都适用,所以c++程序更倾向于使用迭代器而不是下标操作访问容器元素。
20、每个容器类型都定义了自己的迭代器类型,如vector:
vector<int>::iterator;
21、begin和end操作
1)begin返回的迭代器指向第一个元素
2)end返回的迭代器指向vector的“末端元素的下一个”,通常称为超出末端迭代器,即指向一个不存在的元素,因此不能对它进行解引用或自增操作。
22、const iterator 和 const_iterator.
const iterator | 只能改变初始化指定的元素,不能指向其他元素。通常用在需要指向固定元素的迭代器。声明时必须初始化。 |
const_iterator | 不能改变元素的值,但可以改变指向的元素。通常用在只需遍历容器中的元素而不需修改它们。 |
23、iter1 - iter2 表达式使用来计算两个迭代器对象的距离,该距离是名为difference_type的signed类型的值,因为减法可能产生负数。该类型可以保证足够大以存储任何两个迭代器对象间的距离。
24、可以用迭代器算术操作来移动迭代器直接指向某个元素,例如,下面的语句直接定位于vector的中间元素,提高了效率:
vector<int>::iterator mid = vi.begin() + vi.size()/2;
25、任何改变vector长度的操作都会使已存在的迭代器失效。例如,在调用push_back之后就不能再信任指向vector的迭代器的值了。否则程序运行会出错,必须重新指定迭代器指向。
26、bitset类型用来表示二进制位的有序集,基本定义方法例如: bitset<32> bitvec; 其中32表示长度值而不是类型。长度值必须定义为整型字面值常量或是已用常量初始化的整型的const对象。
27、bitset类型的四种初始化方法:
1)bitset<n> b; | b有n位,每位都为0 |
2)bitset<n> b(u); | b是unsigned long型u的一个副本 |
3)bitset<n> b(s); | b是string对象s中含有的位串的副本 |
4)bitset<n> b(s, pos, n); | b是s中从位置pos开始的n个位的副本 |
28、用unsigned 值初始化bitset对象,将该值直接转换为二进制的位模式。如果bitset类型长度大于unsignedlong 值的二进制位数,则其余的高阶位将置0;如果bitset类型长度小于unsigned long 值的二进制位数,则只使用unsigned 值中的低阶位,超过bitset类型长度的高阶位将被丢弃。
29、用string对象初始化bitset对象,而不能直接用字符串字面值初始化。从string对象读入位集的顺序是从右向左,即string对象的最右字符(即下标最大的那个字符)用来初始化bitset对象的低阶位(即下标为0的位)。如果string对象长度大于bitset长度时,取string前面的字串。
32、bitset对象上的操作
b.any() | b中是否存在置为1的二进制位? |
b.none() | b中不存在置为1的二进制位吗? |
os << b | 把b中的位集输出到os流 |
b.to_ulong() | 用b中同样的二进制位返回一个unsigned long值 |
b.flip(pos) | 把b中在pos处的二进制位取反 |
b.flip() | 把b中所有二进制位逐位取反 |
b.reset(pos) | 把b中在pos处的二进制位置为0 |
b.reset() | 把b中所有二进制位都置为0 |
b.set(pos) | 把b中在pos处的二进制位置为1 |
b.set() | 把b中所有二进制位都置为1 |
b.test(pos) | b中在pos处的二进制位是否为1? |
b[pos] | 访问b中在pos处的二进制位 |
b.size() | b中二进制位的个数 |
b.count() | b中置为1的二进制位的个数 |