检测迭代器是否是 std::map 的最后一个元素

Detect if iterator is last element of std::map

这与 this question 相似,但不是重复的。我正在尝试遍历地图并打印每个元素的值,但最后一个元素的输出略有不同。在那个问题中,他们建议使用 map.rbegin().base(),但它对我不起作用。

这是我的代码:

#include <iostream>
#include <map>

int main()
{
    std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
    for (auto iter = charMap.begin(); iter != charMap.end(); iter++)
    {
        std::cout << iter->first << ":\t" << iter->second;
        if (iter == charMap.rbegin().base())
            std::cout << "\t//This is the last element.\n";
        else
            std::cout << "\n";
    }
}

我希望我的输出看起来像这样:

a:    1
b:    2
c:    3
d:    4    //This is the last element. 

但是,我得到了这个输出:

a:    1
b:    2
c:    3
d:    4    

现在我意识到有更好的方法可以做到这一点,但我希望它也能起作用。为什么我不能比较 itercharMap.rbegin().base()

丑。 . .但 。 . .

    auto iterCpy = iter;
    if (++iterCpy == charMap.end())
        std::cout << "\t//This is the last element.\n";

使用 vsoftco 的回答:)

<iterator> 中的 std::next 用作

if (std::next(iter) == charMap.end())
    std::cout << "\t//This is the last element.\n";

相反。

base() 方法 returns 指向一个元素的迭代器,该元素跟在反向迭代器指向的元素之后。这意味着 rbegin().base() 等同于 end()

要完成您的任务,您可以这样做:

#include <iostream>
#include <map>

int main()
{
    std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
    for (auto iter = charMap.begin(); iter != charMap.end(); )
    {
        std::cout << iter->first << ":\t" << iter->second;
        if (++iter == charMap.end())
            std::cout << "\t//This is the last element.\n";
        else
            std::cout << "\n";
    }
}

base() 不 return 相同的元素:

The base iterator refers to the element that is next (from the std::reverse_iterator::iterator_type perspective) to the element the reverse_iterator is currently pointing to. That is &*(rit.base() - 1) == &*rit.

这按预期工作:

#include <iostream>
#include <map>

int main()
{
    std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
    auto last = charMap.rbegin();
    ++last;

    for (auto iter = charMap.begin(); iter != charMap.end(); iter++)
    {
        std::cout << iter->first << ":\t" << iter->second;
        if (iter == last.base())
            std::cout << "\t//This is the last element.\n";
        else
            std::cout << "\n";
    }
}

因为std::reverse_iterator存储偏移量为1的迭代器,所以charMap.rbegin().base() == charMap.end()here 上的图表说明了这一点。

您应该改用 std::prevstd::next 来自 <iterator>:

iter == std::prev(charMap.end())

std::next(iter) == charMap.end()

你觉得哪个更有意义。

实际上,这不会起作用,因为 iter 确实不同于 charMap.rbegin().base()

你的逻辑是正确的,唯一的问题是 charMap.rbegin().base() 迭代器等于 charMap.end(),但是你在 iter 到达 charMap.end() 的时候离开你的 for 语句] 值,所以它永远没有机会在 for 循环内的 if 语句中测试它。

要使其正常工作,您可以按以下方式重写 if 语句:

if (iter->first == charMap.rbegin()->first)
    std::cout << "\t//This is the last element.\n";
else
    std::cout << "\n";

因此您将比较映射键而不是迭代器本身。

这是有效的:

#include <iostream>
#include <map>

int main()
{
    std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
    for (auto iter = charMap.begin(); ;)
    {
        std::cout << iter->first << ":\t" << iter->second;          
        if (++iter== charMap.end()){
            std::cout << "\t//This is the last element.\n"; break;
        }
        else
            std::cout << "\n";
    }

}