深度剖析C++string(上篇)(2)

简介: 深度剖析C++string(上篇)(2)

深度剖析C++string(上篇)(2):https://developer.aliyun.com/article/1624968

4.. string类对象的访问及遍历操作

【】既可以访问字符又可以修改字符,非常的方便。

void string3() {
  string s1("I love you");
  // 获取begin和end迭代器
  std::string::iterator it = s1.begin();
  std::string::iterator it_end = s1.end();
  cout << s1[3] << endl;
  s1[1] = 'u';
  cout << s1 << endl;
  cout << *it << endl; // 输出 I,因为it指向第一个字符
  cout << *(it_end-1) << endl;
  }

上面是正向迭代器的使用,还有一个反向迭代器

std::string::reverse_iterator it = s1.rbegin();
std::string::reverse_iterator it_end = s1.rend();

接下来我们通过迭代器来实现字符串的遍历

void string4() {
  string s("I love you!");
  // 获取begin和end迭代器
  string::iterator it = s.begin();
  string::reverse_iterator it1 = s.rbegin();
  while (it != s.end()) {
    cout << *it << " " ;
    ++it;
  }
  cout << '\n';
  while (it1 != s.rend()) {
    cout << *it1 << " " ;
    ++it1; // 移动到下一个字符(实际上是前一个字符)
  }
  
}

C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型

void string4() {
  string s("I love you!");
  
  // 获取begin和end迭代器
  //string::iterator it = s.begin();
  auto it = s.begin();
  //string::reverse_iterator it1 = s.rbegin();
  auto it1 = s.rbegin();
  while (it != s.end()) {
    cout << *it << " " ;
    ++it;
  }
  cout << '\n';
  while (it1 != s.rend()) {
    cout << *it1 << " " ;
    ++it1; // 移动到下一个字符(实际上是前一个字符)
  }
}

范围for

for (auto ch : s){
    cout << ch << endl;
}

5. auto和范围for(补充)

auto关键字

在这里补充2个C++11的小语法。

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个 不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型 指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期 推导而得。

用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际 只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

auto不能作为函数的参数,可以做返回值,但是建议谨慎使用

auto不能直接用来声明数组

// 编译报错:error C3538: 在声明符列表中,“auto”必须始终推导为同一类型
auto cc = 3, dd = 4.0;
// 编译报错:error C3318: “auto []”: 数组不能具有其中包含“auto”的元素类型
auto array[] = { 4, 5, 6 };

#include <iostream>
using namespace std;
int func1()
{
  return 10;
}
// 不能做参数
void func2(auto a)
{}
// 可以做返回值,但是建议谨慎使用
auto func3()
{
  return 3;
}
int main() {
  return 0;
}

#include <iostream>
using namespace std;
int func1()
{
  return 10;
}
int main() {
  int a = 10;
  auto b = a;
  auto c = 'a';
  auto d = func1();
  // 编译报错:rror C3531: “e”: 类型包含“auto”的符号必须具有初始值设定项
  //auto e;
  cout << typeid(b).name() << endl;
  cout << typeid(c).name() << endl;
  cout << typeid(d).name() << endl;
  int x = 10;
  auto y = &x;
  auto* z = &x;
  auto& m = x;
  cout << typeid(x).name() << endl;
  cout << typeid(y).name() << endl;
  cout << typeid(z).name() << endl;
  return 0;
}

其实对于auto的真正常用的用法是用于迭代器方面,让编译器自己推导迭代器类型,对于复杂的迭代器类型可以简化代码。

下面展示的代码为扩展,别处拷贝过来。

#include<iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
  std::map<std::string, std::string> dict = { { "apple", "苹果" },{ "orange",
   "橙子" }, {"pear","梨"} };
  // auto的用武之地
   //std::map<std::string, std::string>::iterator it = dict.begin();
  auto it = dict.begin();
  while (it != dict.end())
  {
    cout << it->first << ":" << it->second << endl;
    ++it;
  }
    return 0;
}

std::map<std::string, std::string> dict = { { "apple", "苹果" },{ "orange", "橙子" }, {"pear","梨"} };:定义一个std::map对象dict,它包含三个键值对,键是std::string类型的字符串,值也是std::string类型的字符串。

范围for

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此 C++11中引入了基于范围的for循环。

for循环后的括号由冒号“ :”分为两部分:第一部分是范围 内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。

范围for可以作用到数组和容器对象上进行遍历

范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

#include <iostream>
#include <string>
using namespace std;
int main() {
  int arr[] = { 1,2,3,4,5 };
  for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    arr[i] *= 2;
  }
  for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    cout << arr[i] << endl;
  }
  // C++11的遍历
  for (auto &e : arr) {
    e *= 2;
  }
  for (auto e : arr) {
    cout << e << endl;
  }
  string s("hello world!");
  for (auto it : s) {
    cout << it << " " ;
  }
  return 0;
}

结束语

本期讲解就到此结束了,下节我们将继续扩展string的其他接口和函数。

最后感谢各位友友的支持,友友们点个赞吧!!!

目录
相关文章
|
6天前
|
C++ 容器
|
6天前
|
C++ 容器
|
6天前
|
C++ 容器
|
6天前
|
存储 C++ 容器
|
9天前
|
安全 C语言 C++
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
27 4
|
9天前
|
存储 编译器 程序员
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
41 2
|
10天前
|
编译器 C语言 C++
【C++】C++ STL 探索:String的使用与理解(三)
【C++】C++ STL 探索:String的使用与理解
|
10天前
|
存储 编译器 C++
【C++】C++ STL 探索:String的使用与理解(二)
【C++】C++ STL 探索:String的使用与理解
|
10天前
|
编译器 C语言 C++
【C++】C++ STL 探索:String的使用与理解(一)
【C++】C++ STL 探索:String的使用与理解
|
1天前
|
C语言 C++
深度剖析C++string(中)
深度剖析C++string(中)
5 0