迭代器概念
迭代器就是遍历容器的元素
迭代器一般都设计为容器的嵌套类型(设计在容器里面的方法),对于外部来说,我们看不到容器的内部,但是不同容器的底层是不一样的,因为数据结构都不一样.但是每种容器的迭代方式都可以通过++it(运算符重载函数)来体现,用++it这个方式来遍历.
迭代器是一种检查容器内元素并遍历元素的数据类型。C++更趋向于使用迭代器而不是下标操作,因为标准库为每一种标准容器(如vector)定义了一种迭代器类型,而只有少数容器(如vector)支持下标操作访问容器元素。
好处:
迭代器遍历所有容器的方式都是一模一样的!
vector<int>::iterator it = vec.begin();
for (; it != vec.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
unordered_set<int>::iterator it = us.begin();
for (; it != us.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
C++11新标准的foreach语句,对于容器的遍历就是通过迭代器iterator实现的,如果容器没有实现iterator迭代器,那么foreach语句也无法遍历容器,上面vector容器的遍历代码可以简化为:
for (int val : vec) // 实际上是用迭代器遍历容器vec
{
cout << val << " ";
}
cout << endl;
容器选取什么数据结构
根据自己的操作选取合适的
vector 数组:
随机访问多 vec[index] ---------比如排序 用数组作为数据结构比较好(链表只能从这个节点访问到下一个节点)
push back:O(1)
pop back 😮(1)
insert:O(n)
list 链表:
插入 删除多
注意:
1.迭代器相等否,
其实就是看指针指向的地方是否相等
2.容器的begin和end方法,分别返回迭代类型
begin返回的是容器首元素的迭代器的表示 这个对象其实就是指针 指向第一个元素 迭代器++ 即遍历指针++
end返回的是容器末尾元素后继位置的迭代器的表示
++it封装了容器底层元素的迭代过程
*it 即访问迭代器所迭代的元素的值
3.有三种方式来遍历迭代器
foreach其实也是本身用迭代器来迭代,若不提供迭代器方法,它仍然运行不成
auto it = vec.begin()根据右值类型来推导左边的类型
String str1 =“hello” //str1也叫做容器 因为底层放了一组char类型的字符
那么如何遍历底层的这些元素呢?
给String字符串类型提供迭代器的实现
可以不用写迭代器 因为容器自己内部就封装了迭代器 直接用即可
int main()
{
string str1 = "hello world"; // 容器 operator[]
//String::iterator it = str1.begin();
auto it = str1.begin();//右边返回迭代器对象 左边自动匹配it 由此构造出了迭代器it
for (int i = 0; i < str1.length(); ++i)
{
//前置++返回的是对象本身 是引用 ---复数类学的
cout << *it << " ";
++it;
}
for (it = str1.begin(); it != str1.end(); ++it)
{
//前置++返回的是对象本身 是引用 ---复数类学的
cout << *it << " ";
}
cout << endl;
// C++11里用foreach的方式遍历容器内元素的值
for (char ch : str1)
{
cout << ch << " ";
}
cout << endl;
//但是foreach遍历容器 底层仍然是通过迭代器来遍历 它依赖于begin end方法
return 0;
}
基础迭代器写法:
class iterator
{
public:
// iterator
iterator(char *p) {
ptr = p; }//既然要指向一个位置 那么参数接收也得需要一个指针
//提供 ++ * !=基础方法
bool operator!=(const iterator &it)
{
return ptr != it.ptr;
}//迭代器遍历的时候要用到!=运算符重载 这里的比较指的是迭代器底层的指针进行比较
void operator++()
{
ptr++;//迭代器的++也就是指针的++
}
char& operator*() {
return *ptr; }
private:
char *ptr;
};
实现自己的字符串类类型的迭代器
class CMyString
{
public:
CMyString(const char*p = nullptr)
{
if (p != nullptr)
{
// 1.根据p指向得字符串得长度,开辟一块内存空间
mptr = new char[strlen(p) + 1];
// 2.把p指向得字符串拷贝到这块空间上来
strcpy(mptr, p);
}
else
{
mptr = new char[1];
*mptr = 0; // '\0'
}
}
/*
CMyString str1;//str1.mptr ->nullptr
CMyString str2;
str2 = str1;//str1.mptr ->nullptr
*/
~CMyString()
{
delete []mptr;
mptr = nullptr