第三章记录的内容
1.标准库string
string::size_type
string的size()返回的类型为string::size_type。string::size_type是一个无符号类型的值,而且能足够放下任何string对象的大小。该类型是标准库定义的与机器无关配套类型中的一种。
npos表示size_type的最大值,用来表示不存在的位置
std::string str{"213"};
std::string::size_type ii = str.size();
if(str.find("9") == std::string::npos) {
std::cout << "no found";
}
string的下标运算必须大于等于0而小于size(),使用下标运算的时候使用string::size_type类型,这样就保证了不会小于0,只需保证下标小于size的大小。
2.标准库vector
书中说标准库的vector一般情况下创建空的vector比指定大小再添加数据性能更高,只有一种例外,就是所有元素都一样。没具体去验证。
vector中size也是返回size_type,用法和string一样
std::vector<int> vec = {2, 2};
std::vector<int>::size_type si = vec.size();
第三章对string和vector的基本用法做介绍,后续章节的容器还有进一步的介绍
3.数组
理解复杂的数组声明
int *ptrs[10]; //ptr是含有10个整型指针的数组
int (*Parray)[10] = &arr; //Parray指向一个含有10个整型数的数组
int (&arrRef)[10] = arr; //arrRef引用一个含有10个整数的数组
在使用数组的下标,通常使用size_t,size_t是一种机器相关的无符号类型,它被设计得足够大以便能表示内存中任意对象的大小
int aa[] = {99,66,55};
size_t ttt = sizeof (aa);
>指针和数组
在大多数表达式中,使用数组类型的对象其实是使用一个指向数组首元素的指针
使用std::begin()和std::end()实现数组循环
int aa[] = {99,66,55};
auto be = std::begin(aa);
auto en = std::end(aa);
while(be != en) {
++be;
}
一个指针如果指向了某种内置类型数组的尾元素的“下一个位置”,则其具备与vector和end函数返回的与迭代器类似的功能。特别要注意,尾后指针不能执行解引用和递增操作
也可用来初始化vector
int aa[] = {99,66,55};
std::vector<int> ivec(std::begin(aa), std::end(aa));
>指针运算
和迭代器一样,两个指针相减的结果是他们之间的距离。参与运算的两个指针必须指向同一个数组当中的元素
int aa[] = {99,66,55};
auto be = std::begin(aa);
auto en = std::end(aa);
auto n = en - be;
两个指针相减的结果的类型为一种名为ptrdiff_t的标准库类型,和size_t一样,ptrdiff_t也是一种定义在cstddef头文件中的机器相关的类型。因为差值可能为负,所以ptrdiff_t是一种带符号类型
只要指针所指向的是数组中的元素(或者数组中尾元素的下一个位置),都可以执行下标运算
int ia[] = {0, 2, 4, 6, 8};
int *p = &ia[2]; //p指向索引为2的元素
int j = p[1]; //p[1]等价于*(p + 1),就是ia{3]表示的那个元素
int k = p[-2]; //p[-2]是ia[0]表示的那个元素
内置的下标运算符所用的索引值不是无符号类型,这一点与vector和string不一样
>C风格字符串
c风格字符串是把字符串存放在字符数组中并以空字符结束,即在字符串最后一个字符后面跟着一个空字符‘\0’
const char ca1[] = "primer";
尽管c++支持c风格字符串,但在c++程序中最好还是不要使用他们。这是因为c风格字符串不仅使用起来不太方便,而且极易引发程序漏洞,是诸多安全问题的根本原因。
strlen(p) | 返回p的长度,空字符不计算在内 |
---|---|
strcmp(p1, p2) | 比较p1和p2的相等性。如果p1==p2返回0;如果p1>p2,则返回一个正值,如果p1 < p2,返回一个负值 |
strcat(p1, p2) | 将p2附加到p1之后,返回p1 |
strcpy(p1, p2) | 将p2拷贝给p1,返回p1 |
string通过调用c_str()返回c风格字符串
std::string str{"213"};
const char *ccc = str.c_str();
如果执行完c_str()函数后程序想一直都能使用其返回的数组,最好将该数组重新拷贝一份
使用指针和数组很容易出错。一部分的原因是概念上的问题,指针常用于底层操作,因此容易引发一些与繁琐细节相关的错误。其他问题则源于语法错误,特别是声明指针时的语法错误。
现代c++程序应当尽量使用vector和迭代器,避免使用内置数组和指针;应该尽量使用string,避免使用c风格的基于数组的字符串
>多维数组
严格来说,c++语言中没有多维数组,通常所说的多维数组其实是数组的数组。就是数组中存放的还是数组。
int ia[3][4];//大小为3的数组,每个元素是含有4个整数的数组
int ia[3][4] = {
{0, 1, 2},
{3, 4, 5},
{6, 7, 8}
};
使用范围for循环多维数组外层循环必须是引用,是为了避免数组被自动转成指针。如果不使用因为,row的类型为int *,指针类型无法执行范围for就会报错。
for(auto &row : ia) {
for(auto col : row) {
}
}
当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针
int ia[3][4];
int (*p)[4] = ia;//p指向含有4个整数的数组
p = &ia[2]; //p指向ia的尾元素
int (*kkk)[4] = ia;
int *kkkk = *kkk;//kkkk指向内层数组
第三章内容记录到此