双向迭代容器
Iterating over a container bidirectionally
有没有比下面的代码更好的方法来使用相同的迭代器在任一方向上迭代容器?
#include <iostream>
#include <map>
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
std::map<int, int>::iterator startIter = descend ? --(mapp.end()) : mapp.begin();
std::map<int, int>::iterator endIter = descend ? --(mapp.begin()) : mapp.end();
while (startIter != endIter)
{
std::cout << startIter->first << std::endl;
descend ? --startIter : ++startIter;
}
}
编写自文档化代码,一切变得简单。将该循环分解为它自己的函数并使用适当的迭代器调用它。
这就是为什么我们 "reverse iterators" 可以使用它们通过使用正常的前向语义向后穿过容器。
#include <iostream>
#include <map>
template<typename I>
void printMapContainer(I begin, I end)
{
for (;begin != end; ++begin)
{
std::cout << begin->first << "\n";
}
}
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
if (descend) {
printMapContainer(mapp.rbegin(), mapp.rend());
}
else {
printMapContainer(mapp.begin(), mapp.end());
}
}
Is there a better way than the below code, to iterate over a container
in either direction, using the same iterators?
是。使用 std::map::reverse_iterator
。这将是比您发布的代码更好的方法,但不会再使用相同的迭代器,这是您的要求之一。
但是,这比您编写的代码更不容易出错。除此之外,如果已经在 C++ 中,则无需重新发明轮子。
#include <iostream>
#include <map>
template<typename Iterator>
void print(const Iterator Begin, const Iterator End)
{
for(Iterator iter = Begin; iter != End; ++iter)
std::cout << iter->first << "\n";
}
int main()
{
const bool descend = true;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
descend ?
print(mapp.crbegin(), mapp.crend()):
print(mapp.cbegin(), mapp.cend());
return 0;
}
来自 cppreference.com 的图像将以图形方式解释它是如何工作的。
您的代码无效,因为此语句 --(mapp.begin())
导致 UB。我会写一个薄包装:
template<class Iter, class F>
void apply( Iter begin, Iter end, F f, bool forward )
{
while( begin != end )
f( forward ? *begin++ : *--end );
}
或者只是将循环重写为:
auto begin = mapp.begin();
auto end = mapp.end();
while ( begin != end)
{
const auto &p = forward ? *begin++ : *--end;
std::cout << p.first << std::endl;
}
有没有比下面的代码更好的方法来使用相同的迭代器在任一方向上迭代容器?
#include <iostream>
#include <map>
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
std::map<int, int>::iterator startIter = descend ? --(mapp.end()) : mapp.begin();
std::map<int, int>::iterator endIter = descend ? --(mapp.begin()) : mapp.end();
while (startIter != endIter)
{
std::cout << startIter->first << std::endl;
descend ? --startIter : ++startIter;
}
}
编写自文档化代码,一切变得简单。将该循环分解为它自己的函数并使用适当的迭代器调用它。
这就是为什么我们 "reverse iterators" 可以使用它们通过使用正常的前向语义向后穿过容器。
#include <iostream>
#include <map>
template<typename I>
void printMapContainer(I begin, I end)
{
for (;begin != end; ++begin)
{
std::cout << begin->first << "\n";
}
}
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
if (descend) {
printMapContainer(mapp.rbegin(), mapp.rend());
}
else {
printMapContainer(mapp.begin(), mapp.end());
}
}
Is there a better way than the below code, to iterate over a container in either direction, using the same iterators?
是。使用 std::map::reverse_iterator
。这将是比您发布的代码更好的方法,但不会再使用相同的迭代器,这是您的要求之一。
但是,这比您编写的代码更不容易出错。除此之外,如果已经在 C++ 中,则无需重新发明轮子。
#include <iostream>
#include <map>
template<typename Iterator>
void print(const Iterator Begin, const Iterator End)
{
for(Iterator iter = Begin; iter != End; ++iter)
std::cout << iter->first << "\n";
}
int main()
{
const bool descend = true;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
descend ?
print(mapp.crbegin(), mapp.crend()):
print(mapp.cbegin(), mapp.cend());
return 0;
}
来自 cppreference.com 的图像将以图形方式解释它是如何工作的。
您的代码无效,因为此语句 --(mapp.begin())
导致 UB。我会写一个薄包装:
template<class Iter, class F>
void apply( Iter begin, Iter end, F f, bool forward )
{
while( begin != end )
f( forward ? *begin++ : *--end );
}
或者只是将循环重写为:
auto begin = mapp.begin();
auto end = mapp.end();
while ( begin != end)
{
const auto &p = forward ? *begin++ : *--end;
std::cout << p.first << std::endl;
}