STL问题,这段程序错在哪?

a0002 2007-11-15 04:24:18
//我想把一个container的内容append到它的后面
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
vector<int> coll;

for(int i=0; i<10; i++) coll.push_back(i);

vector<int>::iterator pos = coll.begin();
vector<int>::size_type count = coll.size();
back_insert_iterator<vector<int> > iteratorBack(coll);
for( vector<int>::size_type i=0; i<count; ++i,++pos )//error
iteratorBack = *pos ;

return 0;
}
...全文
453 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
batistawjp 2007-11-26
  • 打赏
  • 举报
回复
copy(coll.begin(), coll.end(), back_inserter(coll));
cunsh 2007-11-17
  • 打赏
  • 举报
回复
advance( pos, n );
当pos不是随机访问迭代器时. 这个函数开销也很大啊
a0002 2007-11-17
  • 打赏
  • 举报
回复
容器中的对象比较大,重新构造对象开销很大,每个需要copy的对象只能构造一次,所以最后我选择下面比较笨的方法:

template <class T>
inline void ContainerDouble( T& coll )
{
/*//algorithm 1
if( 1 > coll.size() ) return;

fill_n( back_inserter(coll), coll.size(), *coll.begin() );
typename T::iterator pos = coll.begin();
advance( pos, coll.size() >> 1 );
copy( coll.begin(), pos, pos );*/

/*//algorithm 2
T tmp(coll);
coll.insert( coll.end(), tmp.begin(), tmp.end() );*/

typename T::size_type n, count = coll.size();
typename T::iterator pos;
for ( n=0; n<count; n++ )
{
pos = coll.begin();
advance( pos, n );
coll.insert( coll.end(), *pos );
}
}
weiym 2007-11-16
  • 打赏
  • 举报
回复
把复制的东西直接加到原来的容器里,swap也省了
weiym 2007-11-16
  • 打赏
  • 举报
回复
把复制的东西直接加到原来的容器里,swap也省了
weiym 2007-11-16
  • 打赏
  • 举报
回复
通用的东西效率必然不高了。
反正都是一个一个添加,
LZ也可以用下面的方法。
template <class T>
inline void ContainerDouble( T& coll )
{
T temp(coll);
temp.insert(temp.end(), coll.begin(), coll.end());
temp.swap(coll);
}
weiym 2007-11-16
  • 打赏
  • 举报
回复
通用的东西效率必然不高了。
反正都是一个一个添加,
LZ也可以用下面的方法。
template <class T>
inline void ContainerDouble( T& coll )
{
T temp(coll);
temp.insert(temp.end(), coll.begin(), coll.end());
temp.swap(coll);
}
a0002 2007-11-16
  • 打赏
  • 举报
回复
目前,下面的代码还是我找到的唯一可行的通用代码,但是效率显然不够理想:

template <class T>
inline void ContainerDouble( T& coll )
{
if( 1 > coll.size() ) return;

fill_n( back_inserter(coll), coll.size(), *coll.begin() );
typename T::iterator pos = coll.begin();
advance( pos, coll.size() >> 1 );
copy( coll.begin(), pos, pos );
}
Vitin 2007-11-16
  • 打赏
  • 举报
回复
LZ和weiym的通用算法都不错.

如果要通用性和效率并重,可以考虑为特定的容器特化一些实现.
如LZ原来的算法可以作为list和deque的特化版本;可以用reserve为vector做一个特化版本.
a0002 2007-11-16
  • 打赏
  • 举报
回复
coll.insert( coll.end(), coll.begin(), coll.end() );

象这样的代码,显然是十分危险的,因为它依赖于container的实现,即使是相同类型的container,其实现方法也可能完全不同。

在MS VC++中,这行代码运行结果:
1、vector<int> coll;----可行,结果正确;
2、list<int> coll;----不可行,结果是死循环;
3、deque<int> coll;----不可行,结果是报错。


Vitin 2007-11-15
  • 打赏
  • 举报
回复
要适用所有Back Insertion Sequence的话,建议先将容器中的数据复制到一个临时容器中,再将临时容器的内容插入到原容器中.
a0002 2007-11-15
  • 打赏
  • 举报
回复
“每个容器都有自己的特性,不要有写容器无关代码的幻想。“

那还谈什么generics?

weiym 2007-11-15
  • 打赏
  • 举报
回复
每个容器都有自己的特性,不要有写容器无关代码的幻想。
参考http://stl.winterxy.com/html/item_02.html
a0002 2007-11-15
  • 打赏
  • 举报
回复
非常感谢各位的解答,但是我本来的目的,是写一个模板函数完成这个功能,这样的话,container可能就不限于vector了,也可能是deque、list。

所以,vector::reserve(...)和coll[n]都不再有效!

飞哥 2007-11-15
  • 打赏
  • 举报
回复
没错,村少说的没错。

---------------
迭代器无效。重新分配会使所有指示vecotr中元素的迭代器都无效。因此,利用vector接口,可以查询控制vector重新分配。如果没有显式的控制重新分配,就应该有心里准备 ,要假设所有插入都可能导致重新分配,而且由此会导致所有迭代器失效
预留容量。如果不担心效率或者迭代器失效,就没有必要显示地控制vector内存分配。不过,如果想让程序尽可能地搞笑,或者保证迭代器不会失效,就可以要求vector预先分配足够多的空间来保存所有元素。当然,需要知道它要保存多少个元素,而有时这是无法预知的。


================
又从书上抄了一段。


飞哥 2007-11-15
  • 打赏
  • 举报
回复
晓得了

*pos取的是无意义的值
blldw 2007-11-15
  • 打赏
  • 举报
回复
vector这个容器容量是随着向其内部添加元素数目的增多而逐渐增长的,而且每次增长的量都不一样。可以通过capacity()方法在向容器内添加元素时查看输出内容。而每次增长之前都会分配新的内容,以容纳原来的元素和新增加的元素,这样的话pos这个初始的指向第一个元素的指针也仅仅是指向原来内存内的指针,所以它是不稳定的,要想使你的程序达到你的预定要求,可以使用[]运算符,安全得多,代码参考如下:
#include <iostream>
#include <vector>

using namespace std;

void main()
{
vector<int> coll;

for (int i = 0; i < 10; i++)
{
coll.push_back(i);
}

vector<int>::iterator pos = coll.begin();
back_insert_iterator<vector<int> > iteratorBack(coll);
vector<int>::size_type m = coll.size(), n;
for (n = 0; n < m; n++)
{
*iteratorBack++ = coll[n]; // 你原来的写法不正确
}
for (n = 0; n < coll.size(); n++)
cout << coll[n] << " ";
cout << endl;
}
weiym 2007-11-15
  • 打赏
  • 举报
回复
我同意存少。

wanfustudio
注意LZ是插入容器自己的内容,
虽然back_insert_iterator是调用容器的push_back,
但如果在插入过程中重新分配内存,pos就会失效,它指向的可能不再是有效数据,取它指向的值插入也就没有意义了。
cunsh 2007-11-15
  • 打赏
  • 举报
回复
回复雁南飞的
cunsh 2007-11-15
  • 打赏
  • 举报
回复
回复楼上:

我的意思是让他先增加一下容量. 例如可以:
coll.reserve(coll.size() * 2);

而不是要他 resize() 啊
加载更多回复(15)

64,632

社区成员

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

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