一、C++ 标准库中的string类
1、string类
首先string并不是STL中的,而是一个类string比STL出现的早
从上面可以看出string是从一个类模板中实例化出来的一个对象
在使用string类是必须要包头文件#include< string >
又因为是std中的类,所以要using namespace std; 将std开放,否则就要在使用时加上std::
cpp
//开放std类域
string s1;
//未开放,需要表明是哪个类域的
std::string s2;
2、auto和范围for
auto关键字
<1>
在早期C/C++中auto的含义是:使用auto的变量,是具有自动存储器的局部变量,后来不重要了,那为什么不重要了呢?
因为自动存储器的作用是变量的自动开辟自动释放,但是在后面函数结束后栈会自动回收开辟的空间,在C语言中每一个变量都会在变量类型前加上auto
cpp
//C
int a = 0;
auto int a = 0;
//C++
//报错:c3530:"auto"不能与任何其他类型说明符组合
auto int a = 0;
那为什么在C++中不可以了呢?因为在C++11中重新拾起了这个已经不重要的关键字,并赋予了新的定义:
auto不在是一个存储类型的指示符,而作为一个新的类型指示符来指示编译器,auto指示的变量的数据类型必须由编译阶段推到而来
cpp
#include<iostream>
using namespace std;
int main()
{
int a = 10;
auto b = a;
auto c = 1.1;
//typeid().name() 可以显示数据类型
cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
//报错:c3531:"e": 类型包含"auto"的符号必须具有初始值设定项
//auto e;
return 0;
}
由上面的图可以看出:
1、string是std中的类
2、string是模板的实例化
<2>
auto在声明指针类型变量时,auto 和 auto* 没有区别,但在auto声明引用变量时必须要加上&
cpp
#include<iostream>
using namespace std;
int main()
{
//指针
int a = 0;
auto b = &a;
auto* c = &a;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
//引用
auto& d = a;
d = 10;
cout << a << endl;
return 0;
}
<3>
当在同一行声明多个变量时,变量的数据类型必须相同,否则编译器会报错,因为auto会对第一个变量进行推导,以此推导结果来定义剩下的变量
cpp
auto a = 1, b = 2;
//错误 C3538 在声明符列表中,"auto"必须始终推导为同一类型
auto c = 1, d = 1.1;
<4>
auto不能作为函数的参数,但是可以做函数的返回值,但请谨慎使用,因为在函数多层嵌套时使用auto做返回值会使代码可读性下降
cpp
//auto做函数参数
//报错:c3533:参数不能为包含"auto"的类型
int func1(auto a)
{
return a;
}
//auto做函数返回值
auto func2()
{
int a = 0;
return a;
}
<5>
auto不能声明数组
cpp
//报错:c3318: "auto []": 数组不能具有其中包含"auto"的元素类型
auto array[] = { 1,2,3,4 };
范围for
<1>
对于一个有范围的集合 而言,由程序员来说明循环的范围有些多余,而且还容易范错误,所以在C++11之后引入了基于范围的for循环:
for循环中由 ":" 分为两部分,第一部分用来表示被迭代的变量,第二部分用来表示被迭代的范围。
自动迭代,自动取数据,自动判断结束
<2>
范围for可以作用到数组和容器上进行遍历
cpp
#include<iostream>
#include <string>
using namespace std;
int main()
{
int array[] = { 1, 2, 3, 4, 5 };
// C++98的遍历
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
{
array[i] *= 2;
}
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
{
cout << array[i] << endl;
}
// C++11的遍历
for (auto& e : array)
e *= 2;
for (auto e : array)
cout << e << " " << endl;
string str("hello world");
for (auto ch : str)
{
cout << ch << " ";
}
cout << endl;
return 0;
}
<3>
范围for底层也很简单,容器遍历实际上就是用迭代器进行替换,底层汇编也可以看出
<5>
<5>
<5>
<5>
<5>
二、string类常用接口
只是常用的,其他的只做了解,在需要时能想起来有,并且能查就行,并且下面的都只是C++98版本的,C++11以及往后新加的并没有涉及
1、string类的常见构造(constructor)
constructor函数名称(重点掌握) | 功能说明 |
---|---|
string( ) | 构造空string类对象,即空字符串 |
string (const char* s) | 用C-string来构造string类对象 |
string (size_t n, char c) | string对象中包含 n 个字符 c |
string (const string& str) | 拷贝构造函数 |
cpp
#include<iostream>
#include<string>
using namespace std;
int main()
{
//default (1) string();
string s1;
cout << "s1 : " << s1 << endl;
//from C-string (4) string(const char* s)
string s2("123456");
cout << "s2 : " << s2 << endl;
//copy (2) string(const string & str)
string s3(s2);
cout << "s3 : " << s3 << endl;
//substring (3) string(const string & str, size_t pos, size_t len = npos)
string s4(s2, 2, 3);
cout << "s4 : " << s4 << endl;
//因为此函数不管后面的len填多少到字符串末尾就会结束
//上面函数参数 size_t len有缺省值npos,就是如果不填会默认填最大值
string s5(s2, 1);
cout << "s5 : " << s5 << endl;
//from sequence (5) string(const char* s, size_t n)
string s6("1111111", 4);
cout << "s6 : " << s6 << endl;
//fill (6) string(size_t n, char c)
string s7(7, 'c');
cout << "s7 : " << s7 << endl;
return 0;
}
2、string 类对象的容量操作
3、string类对象的访问及遍历操作
函数名称 | 功能说明 |
---|---|
operator[ ] | 返回pos位置的字符,const string类对象调用 |
-- | -- |
<1>operator[ ]
cpp
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1("1234567");
cout << s1 << endl;
s1[2] = '4';
cout << s1 << endl;
const string s2("111111111");
cout << s2[2] << endl;
return 0;
}