«

[C++Primer学习笔记]第3章 标准库类型

在本章中,简要介绍了string、vector、bitset 三个标准库类型。

1、using声明

  1. 在引用标准库中名字时,需要加上作用域操作符,例如 std::cin 。
  2. 使用 using 声明可以更简洁得使用命名空间,例如只需在文件开头添加using std::cin ,则在下面可以直接引用名字,而不需要再引用该名字的命名空间。
  3. 在头文件中,必须总是使用完全限定的标准库名字,即上面的第一种情况。因为头文件的内容会被预处理器复制到程序中,如果头文件中放置了using声明,就相当于包含该头文件的每个程序中都放置了同一个using声明,不论该程序是否需要using声明。

2、string类型的初始化有以下四种方法

| string s1;         | 默认构造函数,s1为空串         |
| string s2(s1)      | 将s2初始化为s1的一个副本       |
| string s3("value") | 将s3初始化为一个字符串字面值副本 |
| 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::sizetype 类型。特别重要的事,不要把size的返回值赋给一个int 变量。因为 string::sizetype 是unsigned型,它所能存储的长度是int型的两倍,且int型在有些机器上所表示范围太小,极易发生溢出。

8、string对象的大小比较:
1)如果两个string对象长度不同,且短的string对象与长的string对象的前面部分相匹配,则短的string对象小于长的string对象。
2)如果两个string对象的字符不同,则比较第一个不匹配的字符。
例: string a = "Hello", b ="Hello World", c ="Hiya"; 则 a

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::sizetype,所以索引最好也选择string::sizetype类型。

12、在使用下标索引string对象时,必须保证索引值“在上下界范围内”。标准库不要求检查索引值,所以索引的下标越界是没有定义的,这样往往会导致严重的运行时错误。

13、string对象中字符处理,cctype定义的函数:

isalnum()  是否为字母或数字  
isalpha()  是否为字母  
iscntrl()  是否为控制字符  
isdigit()  是否为数字  
isgraph()  是否为除空格之外的打印字符  
islower()  是否为小写  
isprint()  是否为可打印字符,包括空格  
ispunct()  是否为标点符号  
isspace()  是否为标准空白字符,如空格、进纸、换行符、回车、水平或垂直制表符  
isupper()  是否为大写  
isxdigit() 是否为组成16进制数的符号或数字  
tolower()  转换为小写  
toupper()  转换为大写  

14、vector不是数据类型,而只是一个类模板,可用来定义任意多种数据类型。它是同一种类型对象的集合。因此, vector 和 vector 都是数据类型。

15、vector对象的四种初始化方法:

vector<T> v1;       vector保存类型为T的对象。默认构造函数,v1为空。  
vector<T> v2(v1);   v2是v1的一个副本。  
vector<T> v3(n, i); v3包含n个值为i的元素。  
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::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类型的四种初始化方法:

bitset<n> b;             b有n位,每位都为0  
bitset<n> b(u);          b是unsigned long型u的一个副本  
bitset<n> b(s);          b是string对象s中含有的位串的副本  
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的二进制位的个数  
分享