我想知道 C++ 中是否有一些可用的东西可以帮助我们在使用
auto
时迭代两个嵌套循环。比如说,我想将一个数组元素与所有其他元素进行比较。这就是我们传统的做法:
std::vector<int> vec {1, 2, 3, 4};
for (int i = 0; i < vec.size(); ++i)
{
for (int j = i + 1; j < vec.size(); ++j)
{
if (vec[i] == vec[j]) {}
// Compares 1 with 2, 3 and 4
// Compares 2 with 3 and 4
}
}
目的是使用
auto
来实现这一目标。
std::vector<int> vec{1, 2, 3, 4};
for (<auto>& i : vec)
// ^^^^^^^
{
// What should I write here so that I compare only the forward elements?
}
我们可能可以使用这样的东西:
for (auto it = vec.begin(); it != vec.end(); ++it)
{
for (auto jt = it + 1; jt != vec.end(); ++jt)
{
// Do a comparison here.
}
}
第三个快照再次编写更多代码。我希望对普通的第二个快照有更多的了解。
问题本身提到过。
我想知道 C++ 中是否有一些可用的东西可以帮助我们在使用
时迭代两个嵌套循环。auto
std::ranges::iota_view
(自 c++20 起),您可以编写基于嵌套范围的 for
循环,如下所示:
#include <ranges> // std::ranges::iota_view
for (const auto i : std::views::iota(0u, std::size(vec)))
{
for (const auto j : std::views::iota(i + 1u, std::size(vec)))
{
if (vec[i] == vec[j])
{
// .....
}
}
}
此外,这使您能够在循环范围内拥有
i
和 j
const
。
旁注:对于早于 C++20 的编译器,可以轻松实现一个与
std::ranges::iota_view
完全相同的迭代器。
在 c++20 中,也许是这样的?
#include <span>
/*...*/
std::size_t offset = 0;
for (auto &i: vec)
{
for (auto &j: std::span(vec).subspan(++offset))
{
if (i == j) {}
// Compares 1 with 2, 3 and 4
// Compares 2 with 3 and 4
}
}
offset
保证始终为 <= vec.size()
,因此 subspan()
是 明确定义的。
如果您不想引入新变量,这也可以,但可能会产生更详细的汇编并且看起来很不寻常:
for (auto &i: vec)
{
for (auto &j: std::span(vec).subspan(&i - vec.data() + 1))
{
if (i == j) {}
// Compares 1 with 2, 3 and 4
// Compares 2 with 3 and 4
}
}
对于最短的组件,让外部循环在跨度上进行迭代是最好的,这样就不必在每次外部迭代时构造跨度。
std::span span(vec);
std::size_t offset = 0;
for (auto &i: span)
{
for (auto &j: span.subspan(++offset))
{
if (i == j) {}
// Compares 1 with 2, 3 and 4
// Compares 2 with 3 and 4
}
}
您可以在循环中使用
std::any_of
。像这样的东西:
#include <algorithm>
...
std::vector<int> vec = {1, 2, 3, 4, 2};
for(auto it = vec.begin(); it != vec.end(); ++it) {
cout << std::any_of(it + 1, vec.end(), [it](int x){ return x == *it;});
}
这会产生输出
01000
声明一个由两个迭代器成员组成的 SuperIterator 类:
#include <vector>
#include <iostream>
class SuperIterator {
public :
SuperIterator (std::vector<int>::iterator beg, const std::vector<int>::iterator end) : i_ (beg), j_ (beg), end_ (end) {}
~SuperIterator () {}
SuperIterator (const SuperIterator& i) : i_ (i.i_), j_ (i.j_), end_ (i.end_) {}
bool operator == (const SuperIterator& i) const {return (i_ == i.i_) && (j_ == i.j_);}
bool operator != (const SuperIterator& i) const {return !operator == (i);}
SuperIterator& operator = (const SuperIterator& i) {i_ = i.i_; j_ = i.j_; end_ = i.end_;return *this;}
void operator ++ () {
++j_;
if (j_ == end_) {
++i_;
j_ = i_;
}
}
//private :
std::vector<int>::iterator i_, j_;
std::vector<int>::iterator end_;
};
用途:
int main (int argc, char* []) {
std::vector<int> vec {1, 2, 3, 4};
SuperIterator superbeg (vec.begin (), vec.end ()), superend (vec.end (), vec.end ());
for (auto i (superbeg); i != superend; ++i) {
std::cout << *i.i_ << "." << *i.j_ << " ";
}
std::cout << std::endl;
return 0;
}
显示预期结果: 1.1 1.2 1.3 1.4 2.2 2.3 2.4 3.3 3.4 4.4
仅使用了一个自动迭代器。