#include <iostream>
#include <functional>
#include <list>
#include <iterator>
int reduce (std::list<int> l,std::function<int(int a,int b)> f,int start){
int sum=start;
for(auto i1=l.begin();i1!=l.end();++i1){
auto i2=++i1;
sum+=f((*i1),(*i2));
++i2;
}
return sum;
}
int main(){
std::list<int> list{11,4,5,12,6,8,9};
auto a=[](int a,int b){return a+b+1;};
int start=-12;
int o=reduce(list,a,start);
std::cout<<"Output: "<< o<<std::endl;
}
我必须写一个reduce函数,它的第一个参数是一个整数列表,第二个参数是一个函数,它将把容器中的元素减少到一个元素,第三个参数是给定累加的初始值(在这个例子中是-12)。它应该把传递的容器中的元素减少到一个元素,输出应该是50。
当我在for循环中写入cout以查看输出时,迭代器返回了它们应该返回的元素,但为什么我得到了一个inifite循环,是不是因为++i2行将从容器中出来?写这段代码的更好的方法是什么?我怎样才能解决这个问题,使第二个迭代器不会到达容器之外?当涉及到遍历列表容器时,你有什么建议?多谢了
3条答案
按热度按时间fxnxkyjh1#
我想你误解了要求你完成的任务。这是我的看法
这是
reduce
的正常数学定义o0lyfsai2#
问题是,你在循环中将
i1
增加了两次,对于一个奇数元素的列表来说,这将跳过end
迭代器,所以你的循环超出了结尾,进入了 undefined behavior。你需要一次取一个元素,但是要做两次,如果其中一个是
end
迭代器,你需要停止。例如:
我还建议你考虑一下标准库是如何处理泛型容器的,并接受一个迭代器对,这样你就可以使用任何类型的容器了。
laik7k3q3#
在你的代码中有太多的
++
。你不需要任何。你还需要决定如何处理一个有奇数个元素的列表,就像你的例子一样。当元素数是奇数时,以两步递增begin
将永远不会使迭代器等于end
。在下面的代码中,我决定不调用函数,并在下一个迭代器是end
时返回。我认为添加元素只是一个简化的示例,因为对于那个求和,元素以什么顺序添加并不重要,也没有必要成对添加。
Live Demo
std::list
迭代器不是随机访问的,因此it +=2
不起作用。+=
的等价物是std::advance
。它使迭代器前进。std::next
不修改迭代器,而只返回下一个迭代器。代码可以做的更好一点,因为目前它增加相同的迭代器两次。虽然这将是在可读性的代价,也许编译器已经优化了这一点。当有疑问的剖析和研究汇编,但现在我不会担心太多。