我有std::vector
的一些数据(在我的情况下为Points),我想循环遍历所有不同的元素对。对的顺序并不重要(因为我只对点的距离感兴趣)。使用经典的for
循环,我想要做的是:
std::vector<double> vec{-1., 3., 5., -8., 123., ...};
for (std::vector<double>::size_type first = 0; first < vec.size(); ++first) {
for (std::vector<double>::size_type second = first+1; second < vec.size();
++second) {
// Compute something using std::fabs(vec.at(first)-vec.at(second))
}
}
现在我的问题是,如果能够使用基于范围的循环更优雅地实现这一点。
答案 0 :(得分:4)
我不会尝试将它强制转换为基于范围的循环(因为设想内部循环的开始将是棘手的),但我会直接使用迭代器来澄清循环体并使代码更少依赖在你正在使用的特定容器上:
for (auto first = vec.begin(); first != vec.end(); ++first){
for (auto second = first + 1; second != vec.end(); ++second){
// Your vec.at(first) is now simply *first.
}
}
请注意,first + 1
始终有效,因为在评估first
时,vec.end()
永远不会first + 1
。
std::vector::at
检查提供的索引是否在向量的边界内(如果它不在边界内,则抛出std::out_of_range
异常),这是在你的情况下不必要的开销。
答案 1 :(得分:1)
我提供这个答案只是因为OP需要一种方法来做到这一点 基于范围的循环。它并不比普通的循环更优雅。
如果矢量没有重复数字,则可以使用反向迭代而不是从第二个循环中的特定点开始,这样就可以在迭代中使用基于范围的数据。
用于基于范围的反向迭代,用于需要适配器类的循环。
template <typename It>
class reverse_adapter
{
public:
reverse_adapter(It rbegin, It rend)
: _rbegin(rbegin), _rend(rend)
{}
It begin() const { return _rbegin; }
It end() const { return _rend; }
private:
It _rbegin;
It _rend;
};
template<typename Container>
reverse_adapter<typename Container::reverse_iterator> make_reverse(Container& container)
{
reverse_adapter<typename Container::reverse_iterator> adapter(std::rbegin(container), std::rend(container));
return adapter;
}
并在第二个循环中使用此适配器进行反向迭代。
for(auto val : vec)
{
for (auto second_val : make_reverse(vec)) // Start from last to current item in first loop
{
if (val == second_val) break; // Instead of first + 1 in second loop
auto dif = val - second_val;
}
}