int a[5] = {0,5,6,9,8};
vector<int> vec1(a,a+5);
vector<int>::iterator it1 = vec1.begin()+2;
int b[8] = {6,9,12,1,15,10,20,100};
vector<int> vec2(b,b+8);
vector<int>::iterator it2 = vec2.begin() + 2;
cout<<“两个容器的首地址”<<vec1.begin()<<” “<<vec2.begin()<<endl;
cout<<“交换前两个首数”;
cout<<vec1[0]<<” “<<vec2[0]<<endl<<endl;
cout<<“交换前两个迭代器指向的元素:”;
cout<<*it1<<” “<<*it2<<endl;
cout<<it1<<” “<<&vec1[2]<<” “<<it2<<” “<<&vec2[2]<<endl;//这个是所指地址
vec1.swap(vec2);
cout<<“两个容器的首地址”<<vec1.begin()<<” “<<vec2.begin()<<endl;
cout<<“交换后两个首数:”;
cout<<vec1[0]<<” “<<vec2[0]<<endl<<endl;
cout<<“交换后两个迭代器指向的元素:”;
cout<<*it1<<” “<<*it2<<endl;
cout<<it1<<” “<<&vec1[2]<<” “<<it2<<” “<<&vec2[2]<<endl;
//由 上可以看出,虽然两个容器交换了,但是迭代器并没有失效
输出:
两个容器的首地址007E3270 007E32B8
交换前两个首数0 6
交换前两个迭代器指向的元素:6 12
007E3278 007E3278 007E32C0 007E32C0
两个容器的首地址007E32B8 007E3270
交换后两个首数:6 0
交换后两个迭代器指向的元素:6 12
007E3278 007E32C0 007E32C0 007E3278
Press any key to continue
问题来了
1.虽说两个迭代器指向的元素并没有变,但是从输出看他们指向的地址也没变吧 那么是靠什么识别 原指向元素呢?
2.两个容器用swap交换 实际不是其内元素简单的交换 而是两个容器交换,根本是地址也交换了,那么交换后在输出it1 和 it2 的地址怎么和没交换前的地址一样呢?
class vector
{
T* begin;
T* finish;
T* capacity;
};
vector::iterator虽说不一定是用指针实现,但是一定保存了数组中元素的真实内存地址(其实也不是一定,实现也可以保存begin和偏移量,但这么做明显太复杂,实际中都是直接保存元素地址的)。
vector整个swap的时候,其实交换的是双方begin, finish, capacity这三个指针的值。在这个过程中,全部从该vector创建的iterator本身都不会发生任何改变(打个比方就是你换一个手机号,那些存了你以前手机号的人手头的电话号码并不会随之发生改变,除非你告诉他们)。原因是iterator没有改变,所以你打印iterator本身的地址时,得到的仍旧是原来的值。另外,动态数组本身并没有被销毁,只是改变了所属。所以实际两个vector中全部元素的物理地址都没有改变,iterator指向的依然是原来的元素。
<vector>
void swap (vector& x);
Swap content
Exchanges the content of the container by the content of x, which is another vector object of the same type. Sizes may differ.
After the call to this member function, the elements in this container are those which were in x before the call, and the elements of x are those which were in this. All iterators, references and pointers remain valid for the swapped objects.
元素物理地址没有变
例如 交换前后007E3270一直0 007E3278也一直是6啊
变的是指针的内容 也就是迭代器的值 不是迭代器的地址。
swap的机制本人上面说了,其实就是交换三个指针的值而已。原来的两块内存没有任何变化,只是交换了所属对象。容器中的元素的物理地址还是原来的地址,所以迭代器指向的地址才不会改变。
下面是一种常见的迭代器实现方案的简化代码:
template <typename T>
struct base_iterator
{
base_iterator(T* p):m_ptr(p) {}
T* operator->() { return m_ptr; }
// 剩下的若干重载运算符。
T* m_ptr;
};
template <typename T>
class vector
{
typedef base_iterator<T> iterator;
T* begin;
T* finish;
T* capacity;
iterator begin() { return iterator(begin); }
};
获取begin()迭代器实际上就是用begin指针创建了一个iterator对象而已。