swap交换的是变量标识符还是元素?

wpalhm 2007-12-05 10:11:08


list<int> ilst1(10, 2);
list<int> ilst2(10, 3);
list<int>::iterator iter1 = ilst1.begin();
list<int>::iterator iter2 = ilst2.begin();
ilst1.swap(ilst2);
cout << "指向原来list1第一个元素的迭代器现在的值: " << *iter1
<< "\n指向原来list2第一个元素的迭代器现在的值: " << *iter2 << endl;

按书上的说法是:
交换内容:调用完函数后,list1中存放的是list2原来的元素,list2中存放的则是list1原来的元素.list1和list2类型必须相同.改函数的执行速度通常比将list2中的元素复制到list1操作快.
请问到底是交换的元素还是交换了list1和list2这两个变量标识符.如果是交换的元素.怎么可能指向原来位置的迭代器指向的还是同一个值?如果是交换变量标识符,又是怎么做到的?
...全文
194 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yutaooo 2007-12-05
  • 打赏
  • 举报
回复

你已经明白了,我也不用失效这个词了。

iter1经过swap以后,已经没用了,需要再用它访问vector1,就需要重新给它初始化!
wpalhm 2007-12-05
  • 打赏
  • 举报
回复
容器swap和算法swap还是有区别的.就是我给的这个例子就可以看出来.所以容器自带的swap函数不会让迭代器失效.如果失效了怎么可能输出内容来.
算法的swap是基于交换元素的.而根据CoProphet的来说,容器的swap是交换具体容器内指针(指向这个容器头,尾,当前位置等元素)的内容.
wpalhm 2007-12-05
  • 打赏
  • 举报
回复
To yutaooo:
说了swap不会让iterator失效.要不你自己做实验.
wpalhm 2007-12-05
  • 打赏
  • 举报
回复
To CoProphet:
我懂你说的意思了.可能是我理解有点偏差!
yutaooo 2007-12-05
  • 打赏
  • 举报
回复

容器有可能采用pImpl手法实现,也有可能不采用。

采用了pImpl,那么swap就高效,不然,swap效率保持原样。

iter1是vector1的迭代器,经过swap后,却给出了vector2内元素的内容,明显是失效了啊。

对于采用类深拷贝方法来实现的swap,那就可能重新分配内存了,iterator那就更是失效的了。

高效的swap跟浅拷贝看成一线。
霁云 2007-12-05
  • 打赏
  • 举报
回复
我开始强调了是list::swap的实现,不过其实vector::swap的实现,也类似

void swap(_Myt& _X)
{
if (allocator == _X.allocator)
{
std::swap(_First, _X._First);
std::swap(_Last, _X._Last);
std::swap(_End, _X._End); }
else
{
_Myt _Ts = *this;
*this = _X,
_X = _Ts;
}
}

wpalhm 2007-12-05
  • 打赏
  • 举报
回复
我们就拿vector来说吧.
vector容器是一个线性结构.用3个指针存放向量的起始位置.当前最后一个向量的元素的末尾字节和整个容器所占用的内存空间的末尾字节.
假如是M_start指向第一个元素,M_finish指向当前元素,M_end_of_storage指向最后一个的下一个元素.
那么在vector::iterator 中有这样的代码
iterator begin() {return M_start;}//这里的M_start就是指向向量第一个元素.
请问如果是交换这里的指针.那么begin()所指向的内容也是会变化的!
wpalhm 2007-12-05
  • 打赏
  • 举报
回复
To CoProphet:
list::swap内部实现,如果是同样分配器,就是把两个类内部封装的链表头指针和大小信息交换了,比较高效,否则简单的插入新值,删除旧值,这时候比较低效。

================================================
请问所有的容器都是链表的形式吗?未必吧.你这个恐怕只是在链表的条件下成立.我也有这样假设过.所以后面我跟了一个vector<
int>的例子.
霁云 2007-12-05
  • 打赏
  • 举报
回复
list::swap内部实现,如果是同样分配器,就是把两个类内部封装的链表头指针和大小信息交换了,比较高效,否则简单的插入新值,删除旧值,这时候比较低效。
wpalhm 2007-12-05
  • 打赏
  • 举报
回复
swap操作并不会是迭代器失效.为什么不能这样用.说说原因.不能说了半截又不说完.
请问你说的交换指针是什么意思?你能否说清楚点!
HelloDan 2007-12-05
  • 打赏
  • 举报
回复
有这样一句话。
The assignment-relateed operator act on the entire containter, Except for swap, they can be expressed in terms of erase and insert operation.
After swap, iterators continue to refer to the same elements, althought those elements are now in a different containter.

从这句话可以看出用swap并没有实行过擦写,我个人认为其实现相当于交换一个名字吧。
yutaooo 2007-12-05
  • 打赏
  • 举报
回复

变量标识符是不能够交换的呀。语言层次没有这样的概念的。

你代码里的iter1, iter2不应该这样用。swap以后,应该认为这两个iterator失效了。需要重新給初始值。

swap高效,是因为它可能会采取pImpl惯用手法。大致是,将内容放在堆上,在类中持有指向这个内容的指针。交换的时候,交换指针而不进行内容的复制。
HelloDan 2007-12-05
  • 打赏
  • 举报
回复
内部实现我不清楚,但这样交换的Iterator还是有效的。同没交换前一样。
wpalhm 2007-12-05
  • 打赏
  • 举报
回复
再顶一下
wpalhm 2007-12-05
  • 打赏
  • 举报
回复
如果list不够说明这个问题!
毕竟list只要交换头节点下一个指向的内容就可以了.
但是对于vector,deque也是一样的结果.
请问到底是不是交换的元素.书上说到的交换内容和交换元素还是有区别吧!

vector<int> ivec1(10, 2);
vector<int> ivec2(10, 3);
vector<int>::iterator iter1 = ivec1.begin();
vector<int>::iterator iter2 = ivec2.begin();
ivec1.swap(ivec2);
cout << "指向原来ivec1第一个元素的迭代器现在的值: " << *iter1
<< "\n指向原来ivec2第一个元素的迭代器现在的值: " << *iter2 << endl;

结果:

指向原来ivec1第一个元素的迭代器现在的值: 2
指向原来ivec2第一个元素的迭代器现在的值: 3

wpalhm 2007-12-05
  • 打赏
  • 举报
回复

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧