C++迭代器失效的问题汇总
c语言常见问题及解决方法
c语言常见问题及解决方法
一、C语言常见问题及解决方法
1、程序编译错误,原因及解决方法
(1)语法错误:检查程序中出现的缩进、分号、圆括号、大括号的位置,以及程序中变量的定义,保证程序的语法正确。
(2)类型错误:检查程序中关系运算符两边操作数的类型是否匹配,以及变量的使用是否正确,保证每一步运算的类型正确。
(3)变量未声明:检查变量在程序中是否已经声明,声明后才能正确使用。
2、程序运行错误,原因及解决方法
(1)程序中存在逻辑错误:检查程序中的流程是否按设计要求正确,以及程序输出结果是否正确。
(2)程序中存在数据错误:检查程序中的数据是否正确,数据输入、输出以及运算结果都要求正确。
(3)程序运行错误:检查程序中的函数调用是否正确,注意函数的参数和返回值的类型要求。
3、程序编译成功却无法执行,原因及解决方法
这可能是程序出现了语法错误,编译器无法判断,所以编译成功,但是在执行时系统无法识别出程序的命令。
可以通过重新编写程序,查找错误语句的方式查找程序错误,并根据提示修改程序,以解决此问题。
c++ map迭代器原理
c++ map迭代器原理在C++ 中,`std::map` 是一种关联容器,用于存储键值对,并按照键的顺序进行排序。
迭代器是一种用于访问容器元素的对象,可以通过迭代器来遍历和操作容器的内容。
在`std::map` 中,迭代器的底层实现是红黑树(Red-Black tree)。
红黑树是一种自平衡的二叉查找树,它通过保持一些特定的性质来保证树的平衡。
`std::map` 的迭代器可以分为两种类型:`const_iterator` 和`iterator`。
`const_iterator` 用于访问和遍历容器中的元素,并且不允许修改元素的值;`iterator` 除了可以访问和遍历元素之外,还可以修改元素的值。
迭代器的原理如下:1. 迭代器的底层实现是一个指向节点的指针。
每个节点包含一个键值对,以及指向左子节点和右子节点的指针。
2. 在迭代器的初始化过程中,会将指针指向红黑树的根节点。
3. 通过迭代器的操作,可以在红黑树中按照特定的顺序遍历节点。
4. 迭代器的`operator++` 操作会将指针移动到下一个节点,即按照键的顺序遍历红黑树。
5. 通过访问迭代器指向的节点,可以获取节点的键和值等信息。
6. 迭代器的其他操作,如`operator*`、`operator->` 等,可以访问节点的键和值。
需要注意的是,当修改`std::map` 的元素时,可能会导致红黑树的结构发生变化,从而使之前获取的迭代器失效。
为了避免此类问题,应该避免在循环中同时修改和遍历容器。
总结起来,C++ 中的`std::map` 迭代器通过红黑树的底层实现,提供了访问和遍历容器元素的功能。
你可以使用迭代器来遍历`std::map` 中的键值对,并进行相关操作。
C语言编程中的常见问题与解决方案
C语言编程中的常见问题与解决方案C语言作为一门应用广泛的编程语言,在开发软件和系统方面具有重要的地位。
然而,正如其他编程语言一样,C语言编程过程中也会遇到一些常见问题。
本文将探讨一些常见问题,并提供相应的解决方案,以帮助初学者和有经验的开发者更好地应对这些问题。
问题一:语法错误C语言中最常见的问题之一就是语法错误。
这包括标点符号、括号、分号等基本语法错误,以及函数、变量的声明与使用错误等。
当出现语法错误时,编译器会给出相应的错误提示,例如指出错误的行数和错误类型。
解决方法:-仔细检查代码,确保所有的符号都配对使用,并正确使用分号。
-注意变量和函数的声明与使用,确保它们的类型和参数匹配。
-使用代码编辑器或集成开发环境(IDE),这些工具通常会在编写代码时提供实时语法检查功能,帮助避免语法错误。
问题二:逻辑错误逻辑错误是指程序在运行时没有按照预期的方式执行,即结果不符合预期。
这种错误有时很难察觉,因为它们不会引发编译错误或警告。
解决方法:-使用调试工具,例如gdb,对程序进行逐行调试以找出错误所在。
-仔细检查代码,确保逻辑正确。
可以使用流程图或伪代码来描述程序的逻辑。
-使用断言(assert)来验证代码的假设,有助于提前发现错误。
问题三:内存错误内存错误是指在使用指针时,对未分配或已释放的内存进行访问的错误。
这可能导致程序崩溃或产生不可预测的行为。
解决方法:-确认所有的指针都已正确初始化,并在使用完毕后进行适当的内存释放。
-使用动态内存分配函数(malloc、calloc和realloc)时,要确保分配的内存足够,并在使用完毕后进行释放。
-避免在指针为空时进行解引用操作,应先对指针进行空指针检查。
问题四:性能问题C语言相对底层的特性使其具备高性能的潜力,但在编写代码时也容易出现性能问题。
解决方法:-使用适当的算法和数据结构,优化代码的时间和空间复杂度。
-避免重复计算和不必要的循环。
-使用性能分析工具,例如gprof,帮助定位性能瓶颈,并进行优化。
C++迭代器的使用和操作总结
C++迭代器的使⽤和操作总结 迭代器是⼀种检查容器内元素并遍历元素的数据类型。
C++更趋向于使⽤迭代器⽽不是下标操作,因为标准库为每⼀种标准容器(如vector)定义了⼀种迭代器类型,⽽只⽤少数容器(如vector)⽀持下标操作访问容器元素。
⼀.定义和初始化 每种容器都定义了⾃⼰的迭代器类型,如vector:vector<int>::iterator iter; //定义⼀个名为iter的变量 每种容器都定义了⼀对名为begin和en的函数,⽤于返回迭代器。
下⾯对迭代器进⾏初始化操作:vector<int> ivec;vector<int>::iterator iter1=ivec.bengin(); //将迭代器iter1初始化为指向ivec容器的第⼀个元素vector<int>::iterator iter2=ivec.end(); //将迭代器iter2初始化为指向ivec容器的最后⼀个元素的下⼀个位置 注意end并不指向容器的任何元素,⽽是指向容器的最后元素的下⼀位置,称为超出末端迭代器。
如果vector为空,则begin返回的迭代器和end返回的迭代器相同。
⼀旦向上⾯这样定义和初始化,就相当于把该迭代器和容器进⾏了某种关联,就像把⼀个指针初始化为指向某⼀空间地址⼀样。
⼆.常⽤操作 下⾯列出了迭代器的常⽤运算操作:*iter //对iter进⾏解引⽤,返回迭代器iter指向的元素的引⽤iter->men //对iter进⾏解引⽤,获取指定元素中名为men的成员。
等效于(*iter).men++iter //给iter加1,使其指向容器的下⼀个元素iter++--iter //给iter减1,使其指向容器的前⼀个元素iter--iter1==iter2 //⽐较两个迭代器是否相等,当它们指向同⼀个容器的同⼀个元素或者都指向同同⼀个容器的超出末端的下⼀个位置时,它们相等iter1!=iter2 假设已经声明⼀个vector<int>的ivec容器,下⾯⽤迭代器来遍历ivec容器,把其每个元素重置为0:for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)*iter=0; 在C++定义的容器类型中,只有vector和queue容器提供迭代器算数运算和除!=和==之外的关系运算:iter+n //在迭代器上加(减)整数n,将产⽣指向容器中钱前⾯(后⾯)第n个元素的迭代器。
c++中遇到的问题和解决方法
c++中遇到的问题和解决方法C语言是一种广泛应用于编程领域的编程语言,它具有简洁、灵活和高效的特点。
然而,在编程过程中,我们可能会遇到各种各样的问题,这些问题的解决对于程序的正确性和效率至关重要。
本文将讨论在C语言编程中常见的问题及其解决方法。
一、内存管理问题内存管理是C语言编程中非常重要的一部分。
在使用C语言进行编程时,我们需要手动分配和释放内存,这可能会导致一些问题。
常见的问题包括内存泄漏、无效的内存访问和双重释放等。
为了解决这些问题,我们需要了解内存管理的原理,并正确地使用malloc、calloc和free等函数。
解决方法:1. 正确使用malloc、calloc和free等函数来分配和释放内存。
2. 避免重复释放同一块内存。
3. 及时释放不再使用的内存,以避免内存泄漏。
二、指针问题指针是C语言中非常重要的概念之一,它允许我们直接访问内存地址。
在使用指针时,我们需要注意指针的赋值、解引用和传递方式等问题,否则可能会导致程序崩溃或出现未定义行为。
常见的问题包括空指针解引用、野指针和传值调用等。
解决方法:1. 确保指针非空再进行解引用操作。
2. 使用const修饰指针变量,以避免野指针的出现。
3. 使用指针数组或指针指针来传递指向指针的指针。
三、编译错误问题编译错误是C语言编程中最常见的问题之一。
编译器会根据代码的语法和语义规则进行检查,并给出相应的错误提示。
常见的编译错误包括语法错误、类型不匹配错误、未声明的变量错误等。
为了解决这些问题,我们需要仔细检查代码,确保语法和语义正确,并检查变量在使用前是否已经声明和初始化。
解决方法:1. 仔细检查代码的语法和语义,确保没有遗漏或错误的语法。
2. 检查变量在使用前是否已经声明和初始化,避免类型不匹配错误。
3. 调试程序时,使用编译器提供的错误提示和调试工具进行排查。
四、运行时错误问题除了编译错误外,C语言编程中还可能遇到运行时错误。
这些错误可能是由于程序逻辑错误、输入数据不合理等原因导致的。
STL map 内存改变,迭代器失效,_Isnil(_Ptr)和红黑树
STL map 内存改变,迭代器失效,_Isnil(_Ptr)和红黑树最近在做项目时发现一个crash的问题,当时得到的dmp文件显示crash在一个以map为循环变量的循环中,crash位置在如下的代码中标出。
void _Inc(){ // move to node with next larger value#if _HAS_ITERATOR_DEBUGGINGif (this->_Mycont == 0|| _Ptr == 0|| _Isnil(_Ptr)){_DEBUG_ERROR("map/set iterator not incrementable");_SCL_SECURE_OUT_OF_RANGE;}#else_SCL_SECURE_VALIDATE(this->_Has_container());if (_Isnil(_Ptr))---------------------------------------->Why crash here?{_SCL_SECURE_OUT_OF_RANGE;// end() shouldn't be incremented, don't move if _SCL_SECURE is not turned on}#endif /* _HAS_ITERATOR_DEBUGGING */else if (!_Isnil(_Right(_Ptr)))_Ptr = _Min(_Right(_Ptr)); // ==> smallest of right subtreeelse{ // climb looking for right subtree_Nodeptr _Pnode;while (!_Isnil(_Pnode = _Parent(_Ptr))&& _Ptr == _Right(_Pnode))_Ptr = _Pnode; // ==> parent while right subtree_Ptr = _Pnode; // ==> parent (head if end())}}这是C++ 中红黑树迭代器的标准实现,那从这个栈帧能说明我们的代码哪出问题了么?在阅读红黑树的实现代码中有一条语句困扰了我大约半个小时的时间,这条语句就是:_Isnil(_Ptr)标准实现中到处都是这条语句,2年前算法导论系统的学习过一遍,但是由于长时间没有相关的功能需要用到这么深入的知识,有些具体的问题已经记得不是很清楚,于是为了弄对这条语句以及对红黑树有透测的理解,再一次对红黑树知识进行了系统的学习,并翻阅了一些资料,为了使本文自成体系,下面对基础知识进行一些说明。
C语言编译中的常见错误
C语⾔编译中的常见错误C语⾔编译中的常见错误1、警告类错误‘XXX’declare but never used变量XXX已定义但从未⽤过。
‘XXX’is assigned a value which is never used变量XXX已赋值但从未⽤过。
Code has no effect 程序中含有没有实际作⽤的代码。
Non-portable pointer conversion不适当的指针转换,可能是在应该使⽤指针的地⽅⽤了⼀个⾮0的数值。
Possible us e of ‘XXX’before definition表达式中使⽤了未赋值的变量Possibly incorrect assignment这样的赋值可能不正确Redeclaration of ‘main’⼀个程序⽂件中主函数main不⽌⼀个。
Suspicious pointer conversion可疑的指针转换。
通常是使⽤了基本类型不匹配的指针。
Unreachable code程序含有不能执⾏到的代码。
2、错误或致命错误Compound statement missing } in function main程序结尾缺少括号}。
“}”expected;“(”expected等复合语句或数组初始化的结尾缺少“)”;“(”。
Case outside of switch case不属于Switch结构,多由于switch结构中的花括号不配对所致。
Case statement missing ‘:’switch结构中的某个case之后缺少冒号。
Constant expression required定义数组时指定的数组长度不是常量表达式。
Declaration syntax error 结构体或联合类型的定义后缺少分号。
Declaration was expected 缺少说明,通常是因为缺少分界符如逗号、分号、右圆括号等所引起的。
Default outside switch Default部分放到了switch结构之外,⼀般是因为花括号不匹配⽽引起的。
c语言遇到的问题、解决方法及结果
C语言遇到的问题、解决方法及结果1.引言C语言作为一种广泛应用的高级编程语言,常常用于开发系统软件、嵌入式软件以及数据结构等领域。
在使用C语言进行开发过程中,我们会遇到各种问题,本文将讨论常见的问题,并提供相应的解决方法及结果。
2.内存管理问题2.1内存泄漏问题描述:C语言中没有自动内存管理机制,因此在使用动态分配内存时,如果没有释放已使用的内存,就会导致内存泄漏。
解决方法:及时释放已使用的内存是避免内存泄漏的关键。
在每次动态分配内存后,务必记得使用`f re e()`函数释放内存。
结果:通过及时释放内存,可以有效避免内存泄漏问题,提高程序的内存利用效率。
2.2指针问题问题描述:由于C语言中指针的概念较为复杂,容易出现指针使用错误、野指针等问题。
解决方法:在使用指针时,需要保证指针的合法性,避免野指针问题。
同时,可以使用调试工具检查指针的值,以便及时发现和修复指针相关的问题。
结果:通过正确使用指针,可以避免指针相关的错误,提高程序的稳定性。
3.编译问题3.1编译错误问题描述:在使用C语言进行开发时,常常会遇到编译错误,如语法错误、缺少头文件等。
解决方法:仔细检查编译错误的提示信息,根据提示信息进行错误排查。
合理使用编译器提供的调试工具,例如使用`-W al l`选项开启所有警告信息,帮助发现潜在的问题。
结果:通过仔细排查编译错误并进行修复,可以确保程序的正确编译,提高开发效率。
3.2编译器兼容性问题描述:不同的编译器可能对C语言标准的支持程度不同,导致同一份代码在不同编译器下的行为不一致。
解决方法:在开发时,要考虑到目标平台使用的编译器,并根据编译器的要求进行相应的调整和优化。
可以使用条件编译等技术,在不同的编译器下使用不同的代码逻辑。
结果:通过确保程序在目标平台下编译通过,可以提高程序的可移植性和兼容性。
4.性能优化问题4.1程序运行缓慢问题描述:C语言程序在运行过程中可能会因为算法设计不合理、性能瓶颈等原因导致运行缓慢。
C++迭代器失效的几种情况总结
C++迭代器失效的⼏种情况总结⼀、序列式容器(数组式容器)对于序列式容器(如vector,deque),序列式容器就是数组式容器,删除当前的iterator会使后⾯所有元素的iterator都失效。
这是因为vetor,deque使⽤了连续分配的内存,删除⼀个元素导致后⾯所有的元素会向前移动⼀个位置。
所以不能使⽤erase(iter++)的⽅式,还好erase⽅法可以返回下⼀个有效的iterator。
1for (iter = cont.begin(); iter != cont.end();)2 {3 (*it)->doSomething();4if (shouldDelete(*iter))5 iter = cont.erase(iter); //erase删除元素,返回下⼀个迭代器6else7 ++iter;8 }迭代器失效:1void vectorTest()2 {3 vector<int> container;4for (int i = 0; i < 10; i++)5 {6 container.push_back(i);7 }89 vector<int>::iterator iter;10for (iter = container.begin(); iter != container.end(); iter++)11 {12if (*iter > 3)13 container.erase(iter);14 }1516for (iter = container.begin(); iter != container.end(); iter++)17 {18 cout<<*iter<<endl;19 }20 }报错是:vectoriterator not incrementable.迭代器在执⾏++操作时报错!已经失效的迭代器不能再进⾏⾃增运算了。
C语言常见错误分析汇总
C语言常见错误分析汇总1、在一个工程里出现两个main函数时3.obj : error LNK2005: _main already defined in file1.objDebug/HELLO.exe : fatal error LNK1169: one or more multiply defined symbols found 这个就是说,你的main函数重定义了。
你看看是不是你的工程里面,包含了很多个有main函数的文件?2、fatal error C1010: unexpected end of file while looking for precompiled header directive出现这个错误的原因是,工程类型建错了,应该选择win 32 console application3、拼写错误(1)#include <stido.h> //头文件拼写错了void main(){printf("doeifweofupwp");}fatal error C1083: Cannot open include file: 'stido.h': No such file or directory(2)#inculde <stdio.h>//include拼写错了void main(){printf("doeifweofupwp");}fatal error C1021: invalid preprocessor command 'inculde'(无效的预编译命令inculde)(3)#include <stdio.h>void mian() //main拼写错了{printf("doeifweofupwp");}error LNK2001: unresolved external symbol _mainDebug/HELLO.exe : fatal error LNK1120: 1 unresolved externals你用vc建了一个控制台程序,它的入口函数应该是main.4、(1)书写标识符时,忽略了大小写字母的区别。
C++中迭代器原理、失效和简单实现
C++中迭代器原理、失效和简单实现⽬录1. 迭代器的使⽤2. 迭代器的种类3. 迭代器的失效4. 迭代器的实现1.迭代器的使⽤为了提⾼C++编程的效率,STL中提供了许多容器,包括vector、list、map、set等。
有些容器例如vector可以通过脚标索引的⽅式访问容器⾥⾯的数据,但是⼤部分的容器不能使⽤这种⽅式,例如list、map、set。
STL中每种容器在实现的时候设计了⼀个内嵌的iterator类,不同的容器有⾃⼰专属的迭代器,使⽤迭代器来访问容器中的数据。
除此之外,通过迭代器,可以将容器和通⽤算法结合在⼀起,只要给予算法不同的迭代器,就可以对不同容器执⾏相同的操作,例如find查找函数。
迭代器对指针的⼀些基本操作如*、->、++、==、!=、=进⾏了重载,使其具有了遍历复杂数据结构的能⼒,其遍历机制取决于所遍历的数据结构,所有迭代的使⽤和指针的使⽤⾮常相似。
通过begin,end函数获取容器的头部和尾部迭代器,end 迭代器不包含在容器之内,当begin和end返回的迭代器相同时表⽰容器为空。
template<typename InputIterator, typename T>InputIterator find(InputIterator first, InputIterator last, const T &value){while (first != last && *frist != value)++first;return first;}#include <iostream>#include <vector>#include <list>#include <algorithm>using namespace std;int main(int argc, const char *argv[]){int arr[5] = { 1, 2, 3, 4, 5};vector<int> iVec(arr, arr + 5);//定义容器vectorlist<int> iList(arr, arr + 5);//定义容器list//在容器iVec的头部和尾部之间寻找整形数3vector<int>::iterator iter1 = find(iVec.begin(), iVec.end(), 3);if (iter1 == iVec.end())cout<<"3 not found"<<endl;elsecout<<"3 found"<<endl;//在容器iList的头部和尾部之间寻找整形数4list<int>::iterator iter2 = find(iList.begin(), iList.end(), 4);if (iter2 == iList.end())cout<<"4 not found"<<endl;elsecout<<"4 found"<<endl;return 0;}2.迭代器的种类根据迭代器所⽀持的操作,可以把迭代器分为5类。
C语言中的常见错误及解决方法
C语言中的常见错误及解决方法C语言作为一种广泛应用于软件开发领域的编程语言,常常出现一些让初学者或经验不足的程序员困惑的错误。
本文将介绍C语言中常见的错误,并提供解决这些错误的方法。
一、语法错误语法错误是编程过程中最常见的错误之一。
它们通常由于代码中存在语法错误或书写错误而导致。
以下是一些常见的语法错误和解决方法:1.1 缺少分号分号是C语言中语句结束的标志,如果未在语句末尾添加分号,编译器会报错。
解决方法是仔细检查代码,确保每个语句的末尾都有分号。
1.2 括号不匹配在C语言中,括号必须成对出现。
如果括号未正确匹配,编译器会报错。
解决方法是仔细检查代码,确保每个左括号都有对应的右括号。
1.3 大小写错误C语言对大小写敏感,因此函数和变量的命名必须与其声明中的大小写完全匹配。
解决方法是检查代码中的命名,并确保其大小写匹配。
1.4 未定义的变量使用未定义的变量会导致编译器报错。
解决方法是确保在使用变量之前先进行声明或定义。
二、逻辑错误逻辑错误在语法上没有问题,但程序的逻辑流程存在缺陷,导致程序运行不符合预期。
以下是一些常见的逻辑错误和解决方法:2.1 数组越界访问在C语言中,数组的索引从0开始。
如果超出数组的索引范围进行访问,会导致程序崩溃或产生意想不到的结果。
解决方法是检查数组索引,并确保它们在合法范围内。
2.2 逻辑运算错误逻辑运算符(如&&、||和!)在C语言中用于组合表达式。
但是,如果这些运算符的使用不当,可能会导致逻辑错误。
解决方法是仔细检查逻辑运算表达式,并确保其符合预期的逻辑规则。
2.3 循环错误循环是C语言中常用的结构之一,但循环中的错误可能导致程序无限循环或不执行循环体。
解决方法是检查循环条件和循环变量,确保它们能正确地控制循环的执行。
三、内存错误内存错误是C语言中常见的错误类型之一。
以下是一些常见的内存错误和解决方法:3.1 内存泄漏内存泄漏指的是在程序中未正确释放分配的内存空间。
c迭代器失效的问题汇总(Summaryofciteratorfailures)
c++迭代器失效的问题汇总(Summary of c++ iterator failures)Summary of C++ iterator failuresFirst, for vector, adding and deleting operations can cause partial or full iterator invalidation of the container. So why does the iterator fail? The vector element is stored in memory, if the current container has 10 elements, now have to add an element to a container, but the memory behind these 10 elements have a free space, and vector elements must be stored sequentially while access by index, so we can't in memory just to find the element local storage. So vector must be re allocation of storage space, used to store the original elements and the newly added: stored in the storage space of the old elements are copied to the new storage space, then inserts a new element, finally cancelled the old storage space. This happens and must cause all iterators in the vector container to fail. We see how the implementation of the above mentioned allocation and cancellation of memory space achieves the self growth of vector, and the efficiency is extremely low. In order to make the vector container to achieve fast allocation, the actual distribution of the container will be more than the needed space, the vector container reserved this extra storage area for storing newly added elements, without the need for each re allocation of new storage space. You can do this from vector, and capacity and reserve members can see the mechanism. The difference between capacity and size: size is the number of elements that the container currently has, and capacity refers to the total number of elements that the container can store before it must allocate new storage space.The failure of the vector iterator:1. when an element is inserted (push_back), the iterator returned by the end operation is certainly invalid.2. when an element is inserted (push_back), the capacity return value has changed before it has been inserted, and the entire container needs to be reloaded, when the iterator returned by the begin and end operations is invalidated.3. when the delete operation (erase, pop_back), the iterator to the delete point is all dead; the iterator to the element behind the delete point will all fail.The failure of the deque iterator:1. inserting an element in the header or tail of a deque container does not cause any iterator to fail.2. deleting elements at its head or tail will only render the iterator pointing to the deleted element invalid.3., the insertion and deletion operations at any other location in the deque container will cause all iterators pointing to the container element to fail.The failure of the List/set/map iterator:When deleting, the iterator pointing to the deleted node is invalidList intList;List:: iterator it = intList.begin ();While (it = = intList.end ()){It = intList.erase (it);......}Summarize the characteristics of various containers(1) vectorInternal data structure: array.Random access to each element takes time to be constant.The time needed to add or remove elements at the end is independent of the number of elements, and the time required to add or remove elements in the middle or at the beginning varies linearly with the number of elements.Memory can be dynamically added or reduced, but memory management can be done automatically, but programmers can use the reserve () member function to manage memory.The vector iterator will fail when memory is reallocated (theelements it points to are no longer the same before and after the operation). When more than capacity () -size () elements are inserted into the vector, the memory is reallocated, and all iterators are invalidated; otherwise, iterators to any element after the current element are invalidated. When you delete an element, the iterator to any element after the deleted element will fail.(2) dequeInternal data structure: array.Random access to each element takes time to be constant.The time required to add elements at the beginning and end is independent of the number of elements, and the time required to add or remove elements in the middle varies linearly with the number of elements.The element can be dynamically added or reduced, memory management is automatically completed, and no member functions are used for memory management.Adding any of the elements will render the deque iterator invalid. Deleting an element in the middle of an deque will cause the iterator to fail. When an element is deleted at the head or end of a deque, only the iterator pointing to that element is invalid.(3) listInternal data structure: bidirectional circular linked list.You cannot access an element at random.Bidirectional traversal.The time required to add or remove elements at the beginning, end, and center is constant.Can dynamically increase or decrease elements, memory management automatically completed.Adding any element will not make the iterator invalid. When deleting an element, other iterators are not invalidated except for iterators that are present to the deleted elements.(4) slistInternal data structure: one-way linked list.Not bidirectional traversal, can only go from previous to backward traversal.Other features are similar to those of list.(5) stackAdapter, which converts any type of Sequence container into a stack, typically uses deque as a supported sequence container.Elements can only be last in first out (LIFO).Cannot traverse the entire stack.(6) queueAdapter, which converts any type of Sequence container into a queue, typically uses deque as a supported sequence container.Elements can only be first in first out (FIFO).Cannot traverse the entire queue.(7) priority_queueAdapter, which converts any type of Sequence container into a priority queue, typically uses vector as the underlying storage mode.You can only access the first element and cannot traverse the entire priority_queue.The first element is always one of the highest priority elements.(8) setKey unique.The elements are arranged in ascending order by default.If the iterator points to the element, it is deleted,The iterator is invalid. Any other operations that increase and delete elements do not render the iterator invalid.(9) multisetKeys can not be unique.Other features are the same as those of set.(10) mapKey unique.Ascending order of element default keys.If the iterator points to the element being deleted, the iterator is invalid. Any other operations that increase and delete elements do not render the iterator invalid.(11) MultimapKeys can not be unique.Other features are the same as those of map.1. iterator type of containerEach container type defines its own iterator type, such as vector:Vector:: iterator iter;This statement defines a variable called ITER whose data type is the type of iterator defined by vector. Each standard library container type defines a member named iterator, where the iterator is the same as the actual iterator type.2. begin and end operationsEach container defines a pair of functions named begin and end, which are used to return iterators. If there is an element in the container, the iterator returned by begin points to the first element:Vector:: iterator ITER = ivec.begin ();The above statement initializes ITER to the value returned by the vector operation called begin. Assuming that vector is not empty, after initialization, ITER refers to the element as ivec[0].The iterator returned by the end operation points to the next element of the vector's end element, often referred to as the off-the-end iterator, indicating that it points to an element that does not exist. If vector is empty, the iterator returned by begin is the same as the iterator returned by end.The iterator returned by the end operation does not point to any of the actual elements in the vector; instead, it acts as a sentinel, indicating that we have processed all the elements in the vector.3. vector iterator self increasing and quoting operationsThe iterator type defines actions to obtain the elements pointed to by the iterator, and allows the programmer to move the iterator from one element to another.Iterator types can use the iterator operator (* operator) to access the iterator pointing to the R element:*iter = 0;The reference operator returns the element pointed to by the iterator. Suppose that ITER points to the first element of the vector object ivec, then *iter and ivec[0] point to the same element. The effect of the above statement is to assign the value of this element to 0.The iterator uses the increment operator to move forward and the iterator points to the next element in the container. Logically, the iterator's self - increasing operation is similar to the self - increasing operation of the int - type object. The int object, the operation results is the int value "and 1", while the iterator object is the iterator "container in a position to move forward. Therefore, if the ITER refers to the first element, ++iter refers to the second elements.Since the iterator returned by the end operation does not point to any element, it cannot be interpreted or self - extended.4. iterator other operationsAnother of the executable in operation is compared with the iterator: or = =! = = operator to compare two iterators. If two iterator objects point to the same element, they are equal, otherwise they are not equal.5. program examples of iterator applicationsSuppose you have declared a vector type ivec variable, and you want to reset all its element values to 0, and you can do it by subscript:Reset all the elements in ivec / / to 0For (vector:: size_type, IX = 0; IX = = ivec.size (); ++ix)Ivec[ix] = 0;The program uses for to iterate through the elements of the ivec, and the for loop defines an index IX, which is added every time the cycle is iterated, and the IX adds the 1.for loop body to assign each element of the ivec to 0Sum up:1, for the deletion of associative containers (map, list, set) elements, the insertion operation causes an iterator pointing to that element, and other element iterators are not affected.2, the deletion and insertion operations of sequential containers (vector) elements result in invalid iteratorspointing to the element and subsequent elements.About iterators(1) features and operationsThe basic features of the L iterator are:Remove - support the dereference operation so that you can access the value it refers to. That is, if P is an iterator, then *p and p-> should be defined (like pointers);Assignment - an iterator can be assigned to another iterator. That is, if P and Q are iterators, the expression p=q should be defined;Compare -- compare one iterator with another iterator. That is, if P and Q are iterators, the expressions p==q and P, =q should be defined;Traversal -- you can use iterators to iterate through elements in a container, which can be implemented by defining ++p and p++ operations for iterator P.Iterator operations are:Read -- indirectly referencing the element values in a container, such as x = *p, by lifting the reference *;Write -- pass the reference * to assign elements to the container, such as *p = x;Access - referencing elements and their members in containers by subscript and reference, such as p[2] and p->mUsing the iterative increment and decrement operator (+ + and -, + and -, and - = =) traversal, roaming and jumping in the container, such as p++, --p, p+5, p-=8Comparison of using the comparison operator (= =,! =, < >, < =,, > =) to compare two iterators are equal or a man, such as if (P < Q)...... Wihle (P = = c.end ())...... ;(2) classificationDepending on the actions supported by the iterator, the following 5 iterators are defined in STL:L input iterator (input iterator) -- used to read information in a container, but not necessarily to modify it.The input iterator ITER reads the value of the element to which it is pointing through the reference (*iter);In order to enable the input iterator can access all of the elements in the container, must make its support (the prefix / suffix format) + + operator;The input iterator does not guarantee that the order is unchanged in the second traversal of the container; nor does it guarantee that the value of the previously pointing remains unchanged after its increment. That is, any algorithm based oninput iterators should be single pass (single-pass), independent of the value of the previous traversal, and does not depend on the previous value in this traversal.You can see that an input iterator is a one-way, read-only iterator that can be incremented but not incremented, and can only be read and cannot write. Single access read only algorithm.L output iterator (output iterator) -- used to transfer information to a container (modify the value of an element in a container), but it cannot be read. For example, a display is a device that can only be written and cannot read, and can be represented by an output container. Also supports dereferenced and + + operation, but also the single pass. Therefore, output iterators are suitable for single pass write only algorithms.L forward iterator (forward iterator forward iterators) - can only use the + + operator to one-way traverses (not that). As with the I/O iterator, a forward iterator also supports dereferenced and + + operation. Unlike the I/O iterator, the forward iterator is multi pass (multi-pass). That is, it always traverses the container in the same order, and when the iterator is incremented, the same value can still be obtained by lifting the saved iterator reference. In addition, forward iterators can be either read-write or read-only.L (bidirectional iterator) - bidirectional iterators can be used to operator + + and bidirectional traversal container. Others, like forward iterators, also support de reference, and are also multi pass, and are readable, written, or read-only.L random access iterator (random access iterator) -- bidirectional iterator that can access any of the elements in the container directly.Obviously, the 5 iterator categories form a hierarchy: the I/O iterator (+ + can traverse, but the former / latter read-only write only) the most basic, a forward iterator traversal, but can only read and write + + bidirectionaliterator also can read and write but can ++/-- bidirectional traversal, random iterator can in addition to bidirectional traversal but also random visit.(3) pointers and iteratorsSince the iterator is a pointer to a broad sense, is the pointer itself an iterator? In fact, pointers satisfy all iterator requirements, so pointers are iterators.Iterators are interfaces to generic algorithms, and pointers are iterators. So, various STL algorithms can also use pointers to operate nonstandard containers (such as arrays). That is, by using pointers as iterators, you can use the STL algorithm for regular arrays.For example, the sort function sort:Sort (Ran first, Ran last); / / Ran random access iteratorsYes, container C is:Sort (c.begin (), c.end ());对数组一可以改为:(const int的大小= 100;浮[大小];)排序(A,+大小);又例如复制函数复制:复制(第一,在最后,出物);//在和出分别表示输入和输出迭代器对容器C可为:(ostream_iterator out_iter(法院);)复制(C begin(),C(),out_iter);对数组一可以改为:(const int的大小= 100;浮[大小];)复制(A,A + C尺寸,begin());。
C语言命语法错误大全
fatal error C1004: unexpected end of file found未找到文件末尾(可能是括号匹配问题)fatal error C1021: invalid preprocessor command '1nclude'无效的编译预处理命令'1nclude'fatal error C1083: Cannot open include file: 'stdi.h': No such file or directory 不能打开头文件'stdi.h',文件或文件夹不存在error C2101: '&' on constant不能计算常量的地址error C2059: syntax error : 'while'在'while'附近,存在语法错误error C2061: syntax error : identifier 'x'标识符x的附近,存在语法错误error C2065: 'i' : undeclared identifier变量i未定义error C2078: too many initializers数组/结构等变量初始化时的数据太多error C2087: '<Unknown>' : missing subscript丢失数组下标error C2106: '=' : left operand must be l-value'='的左侧应当是左值,即不能是常量error C2115: '=' : incompatible types'='两侧的类型不兼容error C2133: 'a' : unknown sizea(可能是数组名)的大小不确定。
C++——编程常见错误
C++——编程常见错误C++库函数C++标准库⽐C标准库要复杂很多,需要⼤家认真学习。
C++标准库建⽴时间较晚,解决了C标准库的⼀些问题。
通过认真学习、熟练掌握会对代码质量的提⾼有⼀定帮助。
⼀些建议:1. 尽量使⽤迭代器代替下标操作2. 尽量避免使⽤指针和数组,尽可能使⽤vector和迭代器3. 采⽤ string 类型取代 C 风格字符串(使⽤标准库类型 string,除了增强安全性外,效率也提⾼了,因此应该尽量避免使⽤ C 风格字符串)4. ⽤指针操作数组时应⾸先选⽤类似于迭代器的那种⽤法5. const使⽤时,如果等价,尽量将const放在类型后,以避免类似于typedef使⽤中的错误6. ⼀般⽽⾔,应该优先使⽤标准库抽象类⽽少⽤语⾔内置的低级数组和指针。
尤其是应该使⽤ string 类型取代 C 风格以空字符结束的字符数组。
现代 C++ 程序不应使⽤ C 风格字符串。
下⾯是⼀些在我们程序中发现的错误:1. 不会⽤ iterator(其实就是没⽤过STL);for (iter=v.begin; iter!=v.end(); iter++) {...}if (iter == v.end()) {}(漏掉iter == v.end()的判断,直接使⽤*iter。
导致死机。
安徽与宁夏出现过,⾮标准写法的EPG引发。
)2. 多继承时使⽤reinterpret_cast<>转换。
(Hippo中出现过。
死机。
)3. override函数时参数不⼀致导致被认作两个不同的函数。
(Hippo中出现过导致mp对象建⽴失败,视频⽆法播放。
)不严谨的习惯,写程序不留⼼环境、上下⽂1. getString只传buffer指针,不传buffer⼤⼩。
⽰例:int sysNtvuserGet(char *buf);点评:在我们程序员的⼼中总隐藏着⼀些约定、为程序限定⼯作场景。
要知道需求会变的,记忆会被淡忘的,隐藏在内⼼的约定是不⽅便和其他同事交流的。
C++中vector迭代器失效问题详解
C++中vector迭代器失效问题详解⽬录问题:(1)删除vector中所有的偶数(2)vector容器插⼊元素问题迭代器失效原因解决:总结问题:(1)删除vector中所有的偶数#include <iostream>#include <vector>using namespace std;int main(){vector<int> vec;for (int i = 0; i < 10; ++i) {vec.push_back(i);}//把vec容器中的所有偶数删除auto it = vec.begin();for (; it != vec.end(); ++it) {if ((*it) % 2 == 0) {vec.erase(it);}}return 0;}运⾏导致程序崩溃!(2)vector容器插⼊元素问题#include <iostream>#include <vector>using namespace std;int main(){vector<int> vec;for (int i = 0; i < 10; ++i) {vec.push_back(i);}//把vec容器中的所有偶数前⾯添加⼀个⼩于偶数值1的数字auto it = vec.begin();for (; it != vec.end(); ++it) {if ((*it) % 2 == 0) {vec.insert(it,*it-1);}}return 0;}运⾏导致程序崩溃!原因:iterator失效当删除(获取增加)it位置的元素时,导致it后⾯的迭代器全部失效。
因此多次调⽤erase insert导致崩溃迭代器失效原因1 当容器调⽤erase时,当前位置到容器末尾元素的所有的迭代器全部失效2 当容器调⽤insert时,当前位置到容器末尾元素的所有的迭代器全部失效;3 当容器调⽤insert时,如果引起容器内存扩容,原来容器的所有的迭代器就全部失效解释:从向量中删除单个元素(位置)或⼀系列元素([第⼀、最后⼀个])。
STL容器迭代器失效总结
STL容器迭代器失效总结本⽂只总结常见的序列容器(vector、deque、list)和关联容器(set、multiset、map、multimap)的迭代器失效问题。
原迭代器指的是进⾏操作之前保存的迭代器,包括begin()、end()以及其他位置的迭代器。
vector:成员函数push_back():会在容器末尾添加⼀个元素。
如果容器有剩余空间(capacity() > size()),则直接添加新元素到容器尾部。
此时,原迭代器中end()会失效,其他的都不会失效。
否则,会导致容器重新分配内存,然后将数据从原内存复制到新内存,再在尾部添加新元素。
此时,由于内存重新分配,原迭代器(所有)都失效。
成员函数pop_back():直接将容器中的最后⼀个元素删除,原迭代器中end()会失效,其余的都不会失效。
成员函数insert(iterator, n):如果容器有剩余空间,先在容器尾部插⼊⼀个元素,然后将插⼊点及之后的元素都向后移动⼀位,然后在插⼊点创建新元素。
否则,会导致容器重新分配内存,接着将插⼊点之前的元素复制过去,在插⼊点创建新元素,再将插⼊点之后的元素复制过去。
因此,如果没有内存的重新分配,原迭代器中插⼊点及插⼊点之后的迭代器(包括end())都失效。
如果有内存的重新分配,原迭代器(所有)都失效。
成员函数erase(iterator):将删除点及之后的元素都向前移动⼀位,然后删除最后⼀个元素。
因此,原迭代器中删除点之前的迭代器都有效,插⼊点及插⼊点之后的迭代器都失效。
deque:成员函数push_back():会直接在容器末尾添加⼀个元素。
原迭代器中end()会失效,其他的都不会失效。
成员函数push_front():会直接在容器头部添加⼀个元素。
原迭代器中begin()会失效,其他的都不会失效。
成员函数pop_back():会直接删除最后⼀个元素。
原迭代器中end()会失效,其他的都不会失效成员函数pop_front():会直接在容器头部删除⼀个元素。
(CC++学习)38.C++中利用迭代器删除元素的陷阱
(CC++学习)38.C++中利⽤迭代器删除元素的陷阱
前⾔:C++中的容器,分为关联式容器和序列式容器两⼤类,其中关于利⽤迭代器删除元素有很多坑,以前⼀直被坑,但⼀直没整理,今天记⼀下!
⼀. 关联式容器
对于关联式容器(如map,set,multimap,multiset),删除当前节点的迭代器,仅仅会使当前的迭代器失效,只要在 erase 迭代器时,递增当前的迭代器即可。
这是因为map之类的容器,使⽤了红⿊树来实现,插⼊,删除⼀个结点不会对其他结点造成影响。
使⽤⽅式如下例⼦:
⼆. ⾮关联式容器(序列式容器)
对于序列式容器(如vector,deque,list等),删除当前的迭代器会使后⾯所有元素的迭代器都失效。
这是因为vector,deque使⽤了连续分配的内存,删除⼀个元素导致后⾯所有的元素会向前移动⼀个位置。
不过erase⽅法可以返回下⼀个有效的iterator。
具体使⽤⽅式如下,例如:
最后:对于关联式容器,其实也可以使⽤序列式容器这种写法,因为关联式容器的 erase ⽅法也可以返回下⼀个有效的迭代器,⽽序列式容器只能⽤上述删除⽅法。
C++中list的erase()函数问题
C++中list的erase()函数问题
典型错误
for(list::iterator it=li.begin();it!=li.end();it++){
li.erase(it);
}
问题:该程序不能跳出循环
原因:li.erase(it);每次做erase时都有可能使迭代器失效,it++就发⽣错误了。
可以参见effective stl⼀书。
所有容器做erase操作时都有可能使迭代器失效。
因为,当list执⾏erase函数后,会删除对应it的元素,这时迭代器it⾃动更新为下⼀个元素的地址(下⼀个指删除元素的下⼀个)。
这时再执⾏it++,就会把
迭代器it指向删除元素的下下个,导致最终失效,因为跳过⼀个元素。
正确写法有:
while{ it!= li.end(); ){
if (*it % 2)
{
li.erase(it++); //在删除it还在时,对其++
}
else
{
it++;
}
}
或者:
while{ it!= li.end(); ){
if (*it % 2)
{
it=li.erase(it); //erase函数返回值为删除元素的下⼀个元素的迭代器(其实就是⼀个指针),把它赋值给it,就相当于++了。
我更喜欢第⼀种写法。
}
else
{
it++;
}
}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
可动态增加或减少元素,内存管理自动完成,但程序员可以使用reserve()成员函数来管理内存。
vector的迭代器在内存重新分配时将失效(它所指向的元素在该操作的前后不再相同)。当把超过capacity()-size()个元素插入vector中时,内存会重新分配,所有的迭代器都将失效;否则,指向当前元素以后的任何元素的迭代器都将失效。当删除元素时,指向被删除元素以后的任何元素的迭代器都将失效。
while(it != intList.end())
{
it = intList.erase(it);
……
}
总结各种容器特点
(1) vector
内部数据结构:数组。
随机访问每个元素,所需要的时间为常量。
在末尾增加或删除元素所需时间与元素数目无关,在中间或开头增加或删除元素所需时间随元素数目呈线性变化。
迭代--利用增量和减量运算(++和--、+和-、+=和-=)在容器中遍历、漫游和跳跃,例如p++、--p、p+5、p-=8
比较--利用比较运算符(==、!=、<、>、<=、>=)来比较两个迭代器是否相等或谁大谁小,例如if(p < q)……;、wihle(p != c.end())……;
(3)list
内部数据结构:双向环状链表。
不能随机访问一个元素。
可双向遍历。
在开头、末尾和中间任何地方增加或删除元素所需时间都为常量。
可动态增加或减少元素,内存管理自动完成。
增加任何元素都不会使迭代器失效。删除元素时,除了指向当前被删除元素的迭代器外,其它迭代器都不会失效。
总结:
1、对于关联式容器(map, list, set)元素的删除,插入操作会导致指向该元素的迭代器失效,其他元素迭代器不受影响。
2、对于顺序式容器(vector)元素的删除、插入操作会导致指向该元素以及后面的元素的迭代器失效。
关于迭代器
(1)特征与操作
l 迭代器的基本特征有:
遍历--可以使用迭代器来遍历容器中的元素,这可以通过为迭代器p定义++p和p++操作来实现。
迭代器的操作有:
读--通过解除引用*来间接引用容器中的元素值,例如x = *p;
写--通过解除引用*来给容器中的元素赋值,例如*p = x;
访问--通过下标和指向引用容器中的元素及其成员,例如p[2]和p->m
2. begin和end操作
每种容器都定义了一对命名为begin和end的函数,用于返回迭代器。如果容器中有元素的话,由begin返回的迭代器指向第一个元素:
vector::iterator iter = ivec.begin();
上述语句把iter初始化为由名为begin的vector操作返回的值。假设vector不空,初始化后,iter即指该元素为ivec[0].
3.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。
deque迭代器的失效情况:
1.在deque容器首部或者尾部插入元素不会使得任何迭代器失效。
2.在其首部或尾部删除元素则只会使指向被删除元素的迭代器失效。
vector迭代器的失效情况:
1.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。
2.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时begin和end操作返回的迭代器都会失效。
3.在deque容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器失效。
List/set/map迭代器的失效情况:
删除时,指向该删除节点的迭代器失效
list intList;
list::iterator it = intList.begin();
迭代器使用自增操作符向前移动迭代器指向容器中下一个元素。从逻辑上说,迭代器的自增操作和int型对象的自增操作类似。对 int对象来说,操作结果就是把int型值"加1",而对迭代器对象则是把容器中的迭代器"向前移动一个位置".因此,如果iter指向第一个元素,则++iter指向第二个元素。
由于end操作返回的迭代器不指向任何元素,因此不能对它进行解引用或自增操作。
只能访问第一个元素,不能遍历整个priority_queue.
第一个元素始终是优先级最高的一个元素。
(8)set
键唯一。
元素默认按升序排列。
如果迭代器所指向的元素被删除,则该迭代器失效。其它任何增加、删除元素的操作都不会使迭代器失效。
(9)multiset
4. 迭代器的其他运算
另一对可执行于迭代器的操作就是比较:用==或!=操作符来比较两个迭代器,如果两个迭代器对象指向同一个元素,则它们相等,否则就不相等。
5. 迭代器应用的程序示例
假设已声明了一个vector型的ivec变量,要把它所有元素值重置为0,可以用下标操作来完成:
3. vector迭代器的自增和解引用运算
迭代器类型定义了一些操作来获取迭代器所指向的元素,并允许程序员将迭代器从一个元素移动到另一个元素。
迭代器类型可使用解引用操作符(*操作符)来访问迭代器所指向r 元素:
*iter = 0;
解引用操作符返回迭代器当前所指向的元素。假设iter指向vector对象ivec的第一个元素,那么*iter和ivec[0]就是指向同一个元素。上面这个语句的效果就是把这个元素的值赋为0.
C++迭代器失效的问题汇总
首先对于vector而言,添加和删除操作可能使容器的部分或者全部迭代器失效。那为什么迭代器会失效呢?vector元素在内存中是顺序存储,试想:如果当前容器中已经存在了10个元素,现在又要添加一个元素到容器中,但是内存中紧跟在这10个元素后面没有一个空闲空间,而vector的元素必须顺序存储一边索引访问,所以我们不能在内存中随便找个地方存储这个元素。于是vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储空间的元素被复制到新的存储空间里,接着插入新的元素,最后撤销旧的存储空间。这种情况发生,一定会导致vector容器的所有迭代器都失效。我们看到实现上述所说的分配和撤销内存空间的方式以实现vector的自增长性,效率是极其低下的。为了使vector容器实现快速的内存分配,实际分配的容器会比当前所需的空间多一些,vector容器预留了这些额外的存储区,用来存放新添加的元素,而不需要每次都重新分配新的存储空间。你可以从vector里实现capacity和reserve成员可以看出这种机制。capacity和size的区别:size是容器当前拥有的元素个数,而capacity则指容器在必须分配新存储空间之前可以存储的元素总数。
输入迭代器不能保证第二次遍历容器时,顺序不变;也不能保证其递增后,先前指向的值不变。即,基于输入迭代器的任何算法,都应该是单通(single-pass)的,不依赖于前一次遍历时的值,也不依赖于本次遍历中前面的值。
可见输入迭代器是一种单向的只读迭代器,可以递增但是不能递减,而且只能读不能写。适用于单通只读型算法。
(2)deque
内部数据结构:数组。
随机访问每个元素,所需要的时间为常量。
在开头和末尾增加元素所需时间与元素数目无关,在中间增加或删除元素所需时间随元素数目呈线性变化。
可动态增加或减少元素,内存管理自动完成,不提供用于内存管理的成员函数。
增加任何元素都将使deque的迭代器失效。在deque的中间删除元素将使迭代器失效。在deque的头或尾删除元素时,只有指向该元素的迭代器失效。
由end操作返回的迭代器指向vector的"末端元素的下一个".通常称为超出末端迭代器(off-the-end iterator),表明它指向了一个不存在的元素。如果vector为空,begin返回的迭代器与end返回的迭代器相同。
由end操作返回的迭代器并不指向vector中任何实际的元素,相反,它只是起一个哨兵(sentinel)的作用,表示我们已处理完vector中所有元素。
解除--支持解除引用(dereference)操作,以便可以访问它引用的值。即,如果p是一个迭代器,则应该对*p和p->进行定义(似指针);
赋值--可将一个迭代器赋给另一个迭代器。即,如果p和q都是迭代器,则应该对表达式p=q进行定义;
比较--可将一个迭代器与另一个迭代器进行比较。即,如果p和q都是迭代器,则应该对表达式p==q和p!=q进行定义;
键可以不唯一。
其它特点与set相同。
(10)map
键唯一。
元素默认按键的升序排列。
如果迭代器所指向的元素被删除,则该迭代器失效。其它任何增加、删除元素的操作都不会使迭代器失效。
(11)multimap
键可以不唯一。
其它特点与map相同。
1. 容器的iterator类型
每种容器类型都定义了自己的迭代器类型,如vector:
vector::iterator iter;
这条语句定义了一个名为iter的变量,它的数据类型是由vector定义的iterator类型。每个标准库容器类型都定义了一个名为iterator的成员,这里的iterator与迭代器实际类型的含义相同。
// reset all the elements in ivec to 0
for (vector::size_type ix = 0; ix != ivec.size(); ++ix)