size()
size:获取它有多少个字符
size_t size() const;
int main()
{
string s1("hello world");
size_t ret = s1.size();
//计算的是\0前面的字符个数
cout << ret << endl;//11
return 0;
}
三种遍历string的方式
1.下标 + [ ]
仅支持数组不支持链表
int main()
{
string s1 = ("hello world");
for (size_t i = 0; i < s1.size(); i++)
{
cout << s1[i] << " ";
}
//h e l l o w o r l d
cout << endl;
return 0;
}
2.迭代器
迭代器(iterator):像指针一样的东西,不一定是指针
迭代器可以用来访问所有容器(数据结构,链表,树)
it不一定是指针,如果不是指针,*和++会进行重载
begin():返回开始位置的迭代器
end():返回最后一个有效字符的下一个位置
int main()
{
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}
3.范围for
C++11提供的范围for
可以支持所有的容器
自动从s1中取每个值给ch变量,auto自动推导类型
auto:自动赋值,自动迭代,自动判断结束
int main()
{
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
return 0;
}
编译后自动替代为迭代器,底层都是迭代器,范围for的优点是更加方便
<1>.for(auto ch : s)
拷贝不影响string本身
<2>.for(auto& ch : s)
引用会影响string本身
auto
1.auto 可以用来简化代码(类型)
可以用auto来替换长类型
<3>.string::iterator it = s2.begin();
string::iterator:是类型
<3>可以写成
auto it = s2.begin();
2.auto推导类型
根据函数的返回值或右边的类型推导
auto e;(x)
auto c = 'a';
cout << typeid(c).name() << endl;
//char
c:可以是类型或者是对象都打印出类型
auto arrary[] = {4,5,6};
auto 不能定义数组
auto a = 1,b = 2(v)
auto a = 3,b = 3.1(x)
auto 不能做参数
void func2(auto a) (x)
{}
auto 可以做返回值,但要谨慎使用
auto func3()
{
return 1;
}
谨慎使用,如果多层返回
int func1()
{
return 10;
}
auto func2()
{
return func1();
}
auto func3()
{
return func2();
}
int main()
{
auto ret = func3();
return 0;
}
范围for:遍历数组和容器只是为了方便
1.用于容器的使用
2.用于数组的使用可以简化代码
for(auto& e : array)
{
//改变了array中的值,引用
e *= 2;
}
for(auto e : array)
{
e:变量
array:对象
cout << e << " " << endl;
//拷贝不改变原数组的内容
}
底层替换成了指针,数组没有迭代器
auto 在预处理阶段不做处理,在编译阶段处理
预处理阶段:比如宏,条件编译,头文件包含
编译阶段:auto,模版
auto y = &x;
//右边可以是任何类型
auto* z = &x;
//右边必须是指针(地址),因为左边是指针类型
迭代器
迭代器分为正向迭代器和反向迭代器
正向迭代器:iterator 正向走(数组向右走)
反向迭代器:reverse_ iterator 反向走(数组向左走)
反向迭代器
这里可以倒着打印数据
int main()
{
string s1 = ("hello world");
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
// d l r o w h e l l 0
return 0;
}
++肯定封装进一个类中了,不然++不可能倒着走
树,链表倒着遍历必须用这个
下标+[ ]只能用于数组
四种迭代器:
1.普通迭代器(iterator begin() ):可读可写
2.const 迭代器(const_iterator begin() const; ):只能读不能写
const迭代器类似于const int* 只能改变指针的指向,不能改变指向的内容
3.反向迭代器(reverse_iterator rbegin(); )
4.const 反向迭代器(const_reverse_iterator() const; )
int* const 只能改变指向的内容,不能改变指向
capacity
1.size() -> 计算大小,具有通用性
2.length() -> 计算string的大小,具有局限性,不能计算树的大小
length 是string中的size,size比较好用,length是在STL之前就存在的,要向前兼容
string s2("hello world");
cout << s2.length() << endl;
//11
cout << s2.size() << endl;
//11
3.max_size:可以存储的最大的大小(size)
max_size基本不使用
string s2("hello world");
cout << s2.max_size() << endl;
整型的最大值,不同平台、不同容器也不同
4.capacity:空间大小
打印出的是有效字符的个数,不把\0的空间显示出来
string s2("hello world");
cout << s2.capacity() << endl;//15
VS中有数组int buff[16]的存在,第一次是两倍的扩容,后面是1.5倍扩容,但是整体认为扩容2倍
char _buff[16];
char* _arr;
int _size;
int _capacity;
第一次开不超过16字节的空间在buff上,不在堆上,超过buff的空间,会把buff的空间不要,在堆上重新开一块空间,把原数据拷贝过去,但是buff的空间还是存在的
5.reserve:保留,存储
void reserve (size_t n = 0);
会开好比n大的空间( >= n),开的是有效的字符的空间,不包含 \0,提前开好空间
s.reserve(100);
要开100,至少要101的空间
capacity不含\0,底层要比capacity多一个空间
reverse:提前开空间,避免扩容,提高效率
reverse不能改变size(大小)和内容
比如:
size(长度) 10 capacity(空间) 20
1.n < 10
2.10 < n < 20
3.n > 20 扩容
会不会缩容呢?
1 和 2 VS不缩容 : 空间换时间
1 和 2 g++(Linux)缩容 : 珍惜空间