一、标准库类型string
1、使用等号(=)初始化一个变量,执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中;如何不使用等号,则执行的是直接初始化。
2、os<<s 将s写到输出流os当中,返回osis>>s 从is中读取字符串赋给s,字符串以空白分隔,返回is
getline(is,s) 从is中读取一行赋给s,返回is
3、string::size_type类型。是一个无符号类型的值且能存放任何string对象的大小。所有用于存放string类的size函数返回值变量,都应该是string::size_type类型的。
//如果两个string对象的长度不同,且较短string对象的每个字符都与较长string对象对应位置上字符相同,则较短string对象小于较长string对象
//如果两个string对象在某些对应位置不一致,则string对象比较的结果是string对象中第一队相异字符比较的结果。
//所以,str<phrase ; slang>str , slang>phrase
string str = "hello";
string phrase = "hello world";
string slang = "hiya";</span>
4、把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string。
5、字符串字面值与string是不同的类型。
二、标准库类型vector
1、使用vector需包含头文件#include <vector>;
vector是一个类模板,vector<T> var;
引用不是对象,所以不存在包含引用的vector。
<span style="font-size:18px;"> vector<string> svec; //默认初始化,svec不含任何元素
vector<int> ivec;
vector<int> ivec2(ivec); //把ivec的元素拷贝给ivec2;
//列表初始化
vector<string> articles = { "a", "an", "the" };
vector<string> articles1{ "a", "an", "the" };
vector<string> articles2( "a", "an", "the" );//错误,列表初始化只能放在花括号里进行,不能放于圆括号。
vector<int> ivec(10, -1); //10个int类型的元素,都被初始化为-1;
vector<string> svec(10, "hi!") //10个string类型的元素,都被初始化为“hi!”。
vector<int> vi = 10; //错误:必须使用直接初始化的形式指定向量大小</span>
2、向vector对象中添加元素。常常先创建一个空vector,在运用其成员函数push_back向其添加元素。
push_back负责把一个值当成vector对象的尾元素“压入”vector对象的尾端。
<span style="font-size:18px;"> vector<int> v1; //空vector对象
for (int i = 0; i != 100; ++i)
{
v1.push_back(i); //依次把整数值放入v1的尾端
//循环结束后v1有100个元素,值从0到99
}</span>
3、vector对象(以及string对象)的下表运算符可用于访问已存在的元素,不能用于添加元素。
<span style="font-size:18px;">#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string word;
vector <string> v; //创建一个空vector对象
while (cin >> word) //从cin读入词,存放到vector对象中
{
v.push_back(word);
}
for (vector<string>::size_type ix = 0; ix != v.size(); ++ix) //将所有词大写后输出
{
for (string::size_type index = 0; index != v[ix].size(); ++index)
{
v[ix][index] = toupper(v[ix][index]);
}
cout << v[ix] << endl;
}
return 0;
}</span>
三、迭代器
1、迭代器成员begin和end。begin成员负责返回指向第一个元素的迭代器,end成员负责返回指向容器“尾元素的下一位置”的迭代器。如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。
2、*iter 返回迭代器iter所指元素的引用;
iter->mem 解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
<span style="font-size:18px;"> string s("some string");
if (s.begin() != s.end()){ //确保s非空
auto it = s.begin(); //it表示s的第一个字符
*it = toupper(*it); //将当前字符改写为大写形式
}</span>
3、迭代器类型。拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型。
示例:
<span style="font-size:18px;"> vector<int>::iterator it; //it能读写vector<int>的元素
string::iterator it1; //it1能读写string对象中的字符
vector<int>::const_iterator it2; //it2只能读,不能写元素
string::const_iterator it3; //it3只能读字符,不能写</span>
4、begin和end返回类型由对象是否为常量决定。若对象是常量,则返回const_iterator。
为了便于专门得到const_iterator类型返回值,引入函数cbegin和cend。不论vector(或string)对象本身是否为常量,返回值都是const_iterator。
5、凡是使用了迭代器的循环体,都不要向迭代器所属容器添加元素。
四、数组
数组也是存放类型相同对象的容器,这些对象本身没有名字,需要通过其所在位置访问。数组大小确定不变,不能随意向数组中添加元素。
1、数组声明形如a[d],其中a为数组名,d是数组维度。维度必须是一个常量表达式。
2、不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。
3、理解数组声明的含义,最好从数组的名字开始按照由内到外顺序阅读。
4、使用数组下标时,通常定义为size_t类型。size_t是一种机器相关的无符号类型,它被设计的足够大以便能表示内存中任意对象的大小。
习题3.31
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
//初始化数组为其下标值
int a[10];
for (int ix = 0; ix != 10; ++ix)
{
a[ix] = ix;
}
//拷贝为另一个数组
int b[10];
for (int i = 0; i != 10; ++i)
{
b[i] = a[i];
}
//使用vector实现类似功能
vector<int> v(10, 20);
vector<int> v2;
for (vector<int>::iterator iter = v.begin(); iter != v.end(); ++iter)
{
v2.push_back(*iter);
}
return 0;
}
5、在大多数表达式中,是用数组类型的对象其实就是使用一个指向该数组首元素的指针。
示例
int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //ia是一个含有10个整数的数组
auto ia2(ia); //ia2是一个整型指针,指向ia的第一个元素
ia2 = 42; //错误:ia2是一个指针
6、标准库函数begin和end,与容器的两个同名函数功能类似。
用法:
int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //ia是一个含有10个整数的数组
int *beg = begin(ia); //指向ia的首元素的指针
int *last = end(ia); //指向ia尾元素的下一位置的指针
其中尾后指针不能执行解引用和递增操作。
7、下标与指针。
示例
int ia[] = { 0, 2, 3, 4, 6 };
int *p = &ia[2]; //p指向索引为2的元素
int j = p[1]; //p[1]等价于*(p+1),就是ia[3]表示的那个元素
int k = p[-2]; //p[-2]是ia[0]表示的那个元素
标准库限定使用的下标必须是无符号类型,内置的下标运算无此要求,如内置下标运算符可以处理负值。
五、多维数组
严格来说,c++语言中没有多位数组,通常所说的多维数组其实是数组的数组。使用范围for语句处理多位数组时,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型,这是为了避免数组被自动转成指针。
示例
int ia[3][4] = { //三个元素,每个元素都是大小为4的数组
{0,1,2,3}, //第一行的初始化
{4,5,6,7},
{8,9,10,11}
};
size_t cnt = 0;
for (auto &row : ia) //对于外层数组的每一个元素
{
for (auto &col : row) //对于内层数组的每一个元素
{
col = cnt; //将下一个值赋值给该元素
++cnt; //cnt加1
}
}