插入以设置"固定"大小循环

时间:2017-01-25 14:06:21

标签: c++ for-loop insert iterator set

所以我想将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

Live Example

显然end(foo)并没有像我想象的那样奏效。所以...如果我想保存循环大小并计算到那个?

5 个答案:

答案 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不会使迭代器无效,这意味着容器不能是连续的。实际上sets

  

通常实现为二进制搜索树

了解这一点,您实际上只是在继续循环,直到迭代器结束指向最后一个叶子节点为止。当您插入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中所述的临时集合分配。