马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1. 什么是string?
在相识什么是string之前,我们起首必要知道字符串是什么。在C语言中,字符串是指以’\0’末了的一些聚集。同时为了操纵方便,C语言也提供了一些库函数用来操纵这些字符串。
但是,这些函数与字符串是分离开的,不符合OOP的头脑------(面向对象编程(Object Oriented Programming,OOP,面向对象步伐计划)是一种盘算机编程架构。OOP 的一条根本原则是盘算机步伐是由单个可以大概起到子步伐作用的单位或对象组合而成。)。同时必要用户自己管理底层空间,稍不注意就会出现越界访问。
以是为了替换C语言原来令人诟病的字符串体系,就有了string的诞生。因此,可以以为string是C++的字符串控制体系。
2. auto和范围for的使用
2. 1 auto
在C++11之后,尺度委员会赋予auto全新的意义:auto不再是一个存储范例指示符,而是作为一个新的范例指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。
auto作为语法糖,实际上是为了方便步伐员举行更方便的操纵。下面的代码就是全部的使用。
- ////C++20开始支持
- //void Func1(auto x)
- //{
- //
- //}
- //auto做函数返回值,以函数实际 return 返回的值的类型为类型
- //不建议使用auto做函数的返回值。因为函数返回值使用auto的话,确认函数返回值的类型就会变得麻烦
- auto Func(int x)
- {
- auto y = x;
- return y;
- }
- //auto和范围for的使用
- int main()
- {
- //auto的使用
- auto x1 = 1;//auto根据实际对象(1)来自动推断类型
- auto x2 = 1.1;
- auto x3 = "hello world";
- int x4 = 1;
- int& x5 = x4;
- auto x6 = x5;//auto无法判断类型是否是引用,只能根据引用的对象来判断类型,也就是引用对象的类型就是auto的类型
- //然而 auto 诞生的主要目的不是代替这些类型。而是代替一些过长的类型
- //例如
- list<int> It;//定义一个list对象It
- It.push_back(1);
- It.push_back(2);
- It.push_back(3);
- It.push_back(4);//往对象里面尾插1 2 3 4
- list<int>::iterator it1 = It.begin();//定义一个list的迭代器it1,it1指向list对象It的第一个位置,list<int>::iterator是类型
- auto it2 = It.begin();//定义一个list的迭代器it2,it2指向list对象It的第一个位置,auto自动推导类型,因此省去了写前面的一长串
- while (it2 != It.end())
- {
- it2++;
- }
- //另一个例子
- std::map<std::string, std::string> dict;
- std::map<std::string, std::string>::iterator dit1 = dict.begin();
- auto dit2 = dict.begin();//auto代替的就是 std::map<std::string, std::string>::iterator 这一迭代器的类型
- //因此auto可以减轻程序员的编写负担。要是经常需要写那么长一串的类型的话,本来就没剩几根的头发也是岌岌可危了
- //函数的形参为auto,C++20之后才开始支持
- //Func1();
- //函数返回类型为auto,参数为int,函数返回值为int
- Func(1);
-
- return 0;
复制代码 2. 2 范围for
范围for的出现和auto划一,均是为了方便步伐员而推出的语法糖。
- int main()
- {
- // 范围for的使用
- // 适用于容器遍历和数组遍历
- // 原理:范围for底层是迭代器
- string s1("hello world");
- //范围for会把右边的参数自动赋值给左边的变量,左边的变量自动++,直到为空
- //自动取容器的数据赋值给左边的对象
- //自动++,自动判断结束
- for (auto ch : s1)
- {
- //s1的值自动赋值给ch,ch自动++
- cout << ch << " ";
- }
- cout << endl;
- //由于范围for是把右边的值赋值给左边的变量,再对左边的变量进行操作,因此就会出现
- for (auto ch : s1)
- {
- ch++;
- cout << ch << " ";//这里s1的值成功++,并且打印出来
- }
- cout << endl;
- for (auto ch : s1)
- {
- cout << ch << " ";//这里s1的值不变。说明上面的++是将s1拷贝给ch,再在ch中操作,没有对s1本身做出改变
- }
- cout << endl;
- //如果想要在范围for里面改变s1,就需要使用引用
- for (auto& ch : s1)//引用,传址操作
- {
- ch++;
- }
- for (auto ch : s1)
- {
- cout << ch << " ";
- }
- cout << endl;
- //还有另一种情况需要使用引用。当赋值的本体过大,因此拷贝的代价过大,就需要使用引用
- //那么,使用引用之后不想要对本体做出改变怎么办?使用const
- for (const auto& ch : s1)
- {
- //ch++;//编译器报错
- }
- //范围for的使用对象除了容器,还有数组
- int a[] = { 1,2,3,4,5,6,7,8 };
- //正常使用for循环去打印
- for (size_t i = 0; i < sizeof(a) / sizeof(int); i++)
- {
- cout << a[i] << " ";
- }
- cout << endl;
- //使用范围for去打印
- for (auto ch : a)
- {
- cout << ch << " ";
- }
- cout << endl;
- return 0;
- }
复制代码 3. 迭代器的概念、const string的概念
3. 1 迭代器的概念
在相识string是怎么使用之前,我们起首必要知道迭代器的存在。
迭代器(iterator),可以明确为一种像指针、能完成指针全部操纵的对象。其界说为:提供一种方法,使之可以大概依次寻访某个容器所包罗的全部元素,而又无需袒露该容器底层的布局。
由于迭代器自己是抽象的概念,以是会共同下面的代码举行阐明。
- //迭代器的概念
- int main()
- {
- string s1("Hello world!");
- //在C++中,我们想要访问string中的字符串,有两种方式
-
- //1.下标
- //这里之所以能使用下标,是因为在string这个容器中,有关于[]运算符的重载,所以能直接使用[]
- //下标的使用的是有前提的。就是对象的存储空间必须是线性的。如果是链表或者树,那么下标的性能就会大幅下降
- cout << "下标:";
- for (size_t i = 0; i < s1.size(); i++)
- {
- cout << s1[i] << " ";
- }
- cout << endl;
- //2.迭代器
- cout << "迭代器:";
- //string::iterator 说明这是容器 string 的迭代器。it1是实例化的迭代器,可以理解成像s1的指针。但是绝对不是指针,迭代器是全新的概念
- string::iterator it1 = s1.begin();//it1指向的是s1的开头
- while (it1 != s1.end())//这里的end指向的不是world的d,而是d的下一位,通常是"\0"
- {
- cout << *(it1++) << " ";
- }
- cout << endl;
- //迭代器也有反向的
- cout << "反向编译器:";
- string::reverse_iterator rit = s1.rbegin();//这里rit指向的是world中的d
- while (rit != s1.rend())//这里的rend指向的也不是hello中的h,而是h的前一位
- {
- cout << *(rit)++ << " ";//这里的++意味着,反向迭代器不仅仅是定义的反向,运算符重载的方向也是反向的
- }
- return 0;
复制代码 3. 2 const string的概念
- //const string 对象
- int main()
- {
- string s1("Hello world!");
- //const string对象必须使用const修饰的迭代器
- const string s2(s1);
-
- //const_iterator 和 const iterator的区别:前者限定的是迭代器指向的内容,后者限定的是迭代器本身
- //限定迭代器本身的话,就会因为迭代器无法改变,而没办法让 it1++ 访问后面的内容
-
- //string::const_iterator it1 = s2.begin();
- auto it1 = s2.begin();
- while (it1 != s2.end())
- {
- //*it1 += 1;//const 修饰的对象,无法改变大小
- cout << *it1++ << " ";//但是可以改变迭代器的大小,从而改变指向的位置
- }
- cout << endl;
- //const反向迭代器
- string::const_reverse_iterator rit1 = s2.rbegin();
- while (rit1 != s2.rend())
- {
- cout << *rit1++ << " ";
- }
- cout << endl;
- return 0;
- }
复制代码 |