所以我想将set
中所有元素的两倍插回set
。但显然我需要抓住结束迭代器,以便我不再继续迭代新元素。 (别担心,我查了一下,set::insert
没有使迭代器无效:http://www.cplusplus.com/reference/set/set/insert/#validity)所以给定输入set<int> foo = { 1, 2, 3 }
,这就是我所做的:
for(auto it = begin(foo), finish = end(foo); it != finish; ++it) {
foo.insert(*it * 2);
}
我希望我的套装包含:
1,2,3,4,6
惊喜!它包含:
-2147483648,-1073741824,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536 ,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152,65536,98304,131072,196608,262144,393216,524288,786432,1048576,1572864,2097152,3145728,4194304,6291456,8388608 ,12582912,16777216,25165824,333554432,50331648,67108864,100663296,134217728,201356592,268435456,402653184,536870912,805306368,1073741824,1610612736
显然end(foo)
并没有像我想象的那样奏效。所以...如果我想保存循环大小并计算到那个?
答案 0 :(得分:2)
这显然是循环的。每一步的大小都在增加,使得循环永远不会到达终点。
这就像说:从第一个元素开始,从第一个元素开始,并为每个元素继续这样做,当你完成后,再添加一个元素到同一个列表。
为什么会这样结束?
编辑:
回答:&#34;所以...如果我想保存循环大小并计算到那个?&#34;:
int size = foo.size();
std::set<int> bar;
for(auto it = begin(foo); it != end(foo); ++it) {
bar.insert(*it * 2);
}
foo.insert(bar.begin(), bar.end());
答案 1 :(得分:2)
迭代器仍然有效,但由于std::set
是基于节点的容器,因此默认情况下使用std::less<Key>
对元素进行排序
了解迭代器如何跳转到较低的值,使其难以适应finish
Code snippe T:
for( ; it != finish; ++it)
{
auto t = *it ;
std::cout << "At " << t << "\n";
foo.insert( t * 2 ) ;
std::cout << "Inserted " << t*2 << "\n";
}
At 1
Inserted 2
At 2
Inserted 4 <----+
At 3 |
Inserted 6 | <---+
At 4 // jumped back -----+ |
Inserted 8 |
At 6 // Jumped back -----------+
Inserted 12
At 8
.....
答案 2 :(得分:1)
执行此操作的典型方法是迭代源集,并对每个值执行函数,将结果添加到第二个集合中。 完成迭代过程并完全生成第二个集合后,将两个集合合并在一起。
答案 3 :(得分:1)
如果你真的想保存循环大小和数量,你可以这样做:
set<int> foo = { 1, 2, 3 };
int setSize = foo.size();
auto it = foo.begin();
for(int i = 0; i < setSize; ++i) {
foo.insert(*it * 2);
++it;
}
copy(cbegin(foo), cend(foo), ostream_iterator<int>(cout, " "));
这将为您提供输出:1 2 3 4 6
答案 4 :(得分:0)
我相信您的假设是,set
被分配到一个连续的容器中,并假定它最初有足够的空间,因此不必重新分配该连续的容器;在这种假定的情况下,我也希望看到您的行为。 (应该注意的是,即使在这种情况下,这是一个连续的容器,对于这种假设,也需要验证容器的容量,以避免不确定的行为。)
但是,即使在您的问题中,您也指出insert
不会使迭代器无效,这意味着容器不能是连续的。实际上set
s:
通常实现为二进制搜索树
了解这一点,您实际上只是在继续循环,直到迭代器结束指向最后一个叶子节点为止。当您插入set
元素时,编译器-2147483648
的实现会导致这种情况的发生,但这取决于实现,因此在另一个编译器上的行为可能会有所不同。
您正在寻找已定义且独立于编译器的行为。根据您对设置内容的了解,可以对set
进行反向迭代:
for(auto it = rbegin(foo); it != rend(foo); ++it) {
foo.insert(*it * 2);
}
这仅是一个好的解决方案,前提是插入操作创建的元素在之后进行迭代。例如,如果foo
包含负数,则将不起作用。您可以通过检查以下内容来对此进行评估:在if(*cbegin(foo) < 0)
块中,else
可以执行建议的反向迭代循环否则,您需要进行The Quantum Physicist's answer中所述的临时集合分配。