S03字符串、向量和数组
一、命名空间的using声明
1、using namespace::name;:可以直接访问命名空间namespace中的名字name而不需要前缀
注意:每个名字都需要独立的声明,且头文件中不应包含using声明
二、标准库类型string
1、初始化
string s1; //默认初始化,s1是空串
string s2(s1); //s2是s1的副本
string s3 = s1; //s3是s1的副本
string s4("a"); //s4是字面值的副本
string s5 = "a"; //s5是字面值的副本
string s6(n, "a");//s6初始化为连续n个a
注意:拷贝初始化是将等号右侧的初始值拷贝到新创建的string对象中,直接初始化则没有拷贝
2、string主要操作参考cppreference
3、读写string对象
cin >> s;自动忽略开头的空白,从第一个有效字符读直到遇到第一个空白即停止,如输入" hello world "最后s为"hello"getline(cin, line);连续读入直到遇到换行符(换行符也读入)并将读入内容除换行符外存入到line中
4、size()函数返回无符号整型数,因此在有size()的表达式中尽可能避免使用int
decltype(s1.size()) t; //size()的返回值实际为std::size_type类型
t = -1;
cout << t << endl; //输出4294967295
5、+:两个string对象可以直接相加;字面值与string对象相加必须确保+左右至少有一个string对象
string s = "hello" + s0 + "world"; //正确
string s = "hello" + "world" + s0; //错误
注意:为了与C兼容,C++中的字符串字面值并不是string对象,两者是不同的类型
6、范围for(range for):
for ( declaration : expression)
statement
- expression是一个对象,表示一个序列(在statement中不应该存在改变expression序列的语句);
- declaration定义一个变量,用于访问序列中的基础元素
string str("some string");
for(auto c : str) //对于str中的每个字符,每次迭代将下一个字符赋给c
cout << c << endl; //输出some string
注意:有时候在循环中声明为引用时(如auto &c)可以避免因元素类型很大导致的拷贝开销很大
三、标准库类型vector
1、vector:表示对象的集合,其中所有对象的类型都相同,也称为容器,vector是模板而非类型
2、初始化
vector<T> v1 //v1是空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1) //v2中包含有v1所有元素的副本
vector<T> v2 = v1 //等价于v2(v1)
vector<T> v3(n, val) //v3包含了n个重复的val元素
vector<T> v4(n) //v4包含了n个重复的执行了值初始化的对象
vector<T> v5{a, b, c} //v5包含了初始值个数的元素,每个元素赋予相应的初始值
vector<T> v6 = {a, b, c} //等价于v5{a, b, c}
圆括号:提供的值用来构造vector对象
花括号:提供的值用来列表初始化vector对象
注意:使用拷贝初始化(”=”)时只能提供一个初始值
注意:如果提供的是类内初始值,则只能用拷贝初始化或花括号形式初始化
注意:如果提供的是初始元素的列表,则只能在花括号中列表初始化,不能使用圆括号
3、对vector使用范围for时需要确保不会改变vector的序列
4、vector主要操作主要操作参考cppreference
四、迭代器介绍
1、begin返回指向第一个元素的迭代器,end返回指向尾元素下一个元素的迭代器,当容器为空时,begin和end返回同一个迭代器,都是尾后迭代器
2、迭代器的比较只能发生在同一个容器的迭代器之间,不同容器的迭代器不能比较
3、iterator主要操作参考cppreference
注意:iterator的<,<=等比较基于两个迭代器在容器中的相对位置给出结果
注意:由于迭代器的特殊性,所有使用到迭代器的循环体,都不能改变迭代器所属的容器,否则会使迭代器失效
五、数组(内置数组类型)
1、数组的大小不变,不能增减元素,当元素个数不定时使用vector,数组基本用法与vector一致
2、定义数组时必须指明数组的类型,不允许使用auto来推断,数组的元素是对象
3、字符数组需要注意结尾’\0’
char a1[] = {'C', '+', '+'}; //没有空字符
char a2[] = {'C', '+', '+', '\0'}; //有空字符
char a3[] = "C++"; //自动添加空字符,效果和a2[]相等
4、对数组名的操作很多情况下可以认为是对常量指针的操作
(1)由于对数组的操作很多情况下被转换为对指针的操作,因此当auto数组名时实际定义是指针
int ia[] = {0, 1}, ic[] = {2};
auto ib(ia); //实际执行过程类似auto ib(&ia[0]),且auto忽略顶层const,因此ib是int*
ib = 42; //错误,ib是指针int*并被初始化与ia相同
ib = ic; //正确,此时ib指向ic[0]
(2)然而当decltype数组名时实际定义的是数组,因为decltype不会转换为&ia[0]
int ia[] = {0, 1};
decltype(ia) ib; //此时ib是指向两个int元素的数组,即ib的类型是int[2]
5、指针也是迭代器,数组的指针可以完成迭代的操作,但与类类型略有区别
int ia[] = {0, 1, 2};
int *beg = begin(ia); //获取首元素指针
int *en = end(ia); //获取尾后指针,尾后指针不能解引用和递增
6、下标运算符所用到的索引值不是无符号类型,可以是负数,但结果是要仔细考虑的
7、尽可能使用vector、string而不是内置数组类型
六、多维数组
1、使用范围for处理多维数组
for(auto &row : ia)
for(auto &col : row)
statements //对数组元素进行操作,需要引用
for(const auto &row : ia)
for(auto col : row)
statements //对数组元素只读,可以不引用,但是外层for依然需要引用,避免数组被自动转化成指针
for(auto row : ia)
for(auto col : row)
statements //错误,外层循环自动将row转化成int*指针,内层循环试图在int*指针中遍历是错误的
注意:处理多维数组时,除了最内层循环外,其他控制变量都应该是引用类型
1189

被折叠的 条评论
为什么被折叠?



