菜狗的C++ primer读书笔记:第三章 字符串、向量和数组

来源:互联网 发布:森田疗法 知乎 编辑:程序博客网 时间:2024/06/02 01:59

命名空间的using声明

1.使用命名空间的一个名字:using Namespace::Name(用到的每个名字都必须有自己的声明语句,而且每句话都得以分号结束)

   使用命名空间: using namespace Namespace

2.头文件中不应包含using声明,对于某些程序来说由于不经意包含了一些名字,可能会产生始料未及的名字冲突。


标准库类型string

1.如何初始化类的对象是由类本身决定的。一个类可以定义很多种初始化对象的方式,只不过这些方式之间必须有所区别。

2.对string用字符串字面值初始化时,string对象拷贝除最后的空字符外的其他所有字符。

3.如果使用=初始化,则为拷贝初始化,相反则为直接初始化。对于用到多个值初始化时,一般采用直接初始化,如string s(n,'c') 。

4.一个类除规定初始化其对象的方式外,还要定义对象上所能执行的操作。其中类既能定义通过函数名调用的操作,也能定义<<、+等各种运算符在该类对象上的新含义。

5.在string对象进行读取操作时,会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白为止。用getline(is,s)则可读取一整行,如果输入一开始就是换行符则得到空string(得到的string对象中并不包含该换行符)。

6.string库中size函数返回的是string::size_type类型的值。此时尽量用auto和decltype来声明变量,且当表达式中有size()函数时不再使用int,避免混用两种类型可能带来的问题。

7.string比较规则:

①.两对象长度不同,且较短对象每个字符都与较长对象对应位置字符相同,则较短对象小于较长对象。

②.若两对象在某些对应位置上不一致,则比较结果是两对象中第一对相异字符比较的结果。

8.标准库允许把字符字面值和字符串字面值转换成string对象,但必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string,即不能把字面值直接相加。(字符串字面值和string是不同的类型)

9.C语言头文件形如name.h,C++则将这些名字命名为cname。特别的在名为cname的头文件中定义的名字从属于空间std。处理string对象中的字符要用到cctype头文件中的函数。

10.范围for循环遍历给定序列中每个元素,并对序列中的每个值执行某种操作。通过使用auto关键字让编译器决定循环变量的类型,且当要使用范围for语句改变序列中的元素时,必须把循环变量定义成引用类型。

11.对于逻辑与运算符(&&)来说,C++规定只有当左侧运算对象为真时才会检查右侧运算对象的情况。

12.使用下标必须确保其在合理范围之内,一种方法是总是设下标类型为string::size_type,因此此类型是无符号数,可以确保下标不会小于0。无论何时用到字符串的下标,都应注意检查其合法性。


标准库类型vector

1.不存在包含引用的vector,除此之外其他大多数内置类型和类类型都可以构成vector对象,甚至组成vector的元素也可以是vector。

2.初始化方式的例外情况:

①.使用拷贝初始化时只能提供一个初始值。

②.如果提供的是一个类内初始值,则只能使用拷贝初始化或花括号形式初始化。

③.如果列表初始化,只能用花括号不能用圆括号。

3.通常情况下,可以只提供vector对象容纳的元素数量而略去初始值。此时库会创建一个值初始化的元素初值并赋给容器中的所有元素,初值由vector对象中元素的类型决定。

4.在某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。且想要列表初始化vector对象,花括号里的值必须与元素类型相同。

5.push_back函数负责把一个值当成vector对象的尾元素push到vector对象的back 。

6.C++标准要求vector应该能在运行时高效快速地添加元素。因此既然vector对象能高效地增长,那么在定义vector对象的时候设定其大小也就没什么必要了,事实上如果这么做性能可能更差。


迭代器

1.begin返回容器的第一个元素,end返回容器尾元素的下一个位置。特殊情况下如果容器为空,则begin和end返回的是同一个迭代器。(此处的begin和end函数是vector类中的成员函数)

2.拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器类型,一般用auto声明迭代器。

3.如果对象只需读操作而无需写操作的话最好使用常量类型,C++11引入了两个新函数,分别是cbegin和cend。

4.*(it).mem等价于it->mem。

5.某些对vector对象的操作会使迭代器失效,一个限制是不能再范围for循环内向vector对象添加元素,另外一个限制是任何一种可能改变vector对象容量的操作比如push_back都会是vector对象的迭代器失效。

6.迭代器间的距离类型是名为difference_type的带符号型整数。所谓距离指的是右侧的迭代器向前移动多少位置就能追上左侧的迭代器。(右侧为大)

7.C++没有定义迭代器的加法运算,这在程序中是没有意义的。所以注意在运用迭代器时表达式的合法性。


数组和多维数组

1.数组的维度必须是常量表达式。

2.字符数组和string类型的一个区别,字符数组用字面值常量初始化时会自动添加表示字符串结束的空字符。

3.数组声明:

int a[10];  //a是含有10个整数的数组

int *p[10];   //p是含有10个整型指针的数组

int (*pp)[10]=&a;   //pp是指向a的指针等价于 int *pp=a;

int (&r)[10]=a;   //r引用a

int *(&rr)[10]=p;   //rr引用p

从数组的名字开始按照由内向外的顺序阅读。

4.无参数的函数不是常量表达式,只有constexpr类型的函数才是。

5.使用数组下标时,通常将其定义为size_t类型,在cstddef头文件里。

6.auto a2(a) 等价于 auto a2(&a[0]) ,a是一个整型数组,这样声明后a2是一个整型指针,而decltype(a) a3得到的a3类型是数组。

7.同样的,指针也有begin和end函数,它们被定义在iterator文件中。(此处begin和end不是成员函数)

8.两个指针相减的结果的类型是一种名为ptrdiff_t的标准库类型,也被包含在cstddef头文件中。

9.在处理与旧代码的接口时需注意的地方:

①.混用string对象和C风格,注意string专门为此提供的一个c_str的成员函数

②.使用数组初始化vector对象,如vector<int> ivec(begin(a),end(a))

10.多维数组使用范围for循环时,除了最内层的循环外其他所有循环的控制变量都应该是引用类型。外层的控制变量作为内层的序列变量。

11.在声明多维数组的指针时注意圆括号的使用,同3。

12.下标运算符的数目决定给定的是一个元素还是内层数组。

13.一般来说,应该优先选用标准库提供的类型,之后再考虑C++语言内置的底层的替代品数组或指针。



0 0
原创粉丝点击