将迭代器设置为具有最高键的值

set iterator to value with highest key

我有一个带有分数的字符串集合,我想找到分数最高的字符串。现在,由于 std::map 将其项目按键排序,我认为这将是一个完美的存储 class。现在我在将迭代器指向最后一项时遇到了问题(以检索得分最高的值)。我得到的是:

int main(void)
{

    map<double, string> m;

    m.insert(std::pair<double,string>(79.43567,"ARH1265"));
    m.insert(std::pair<double,string>(69.83569,"ZRE5265"));
    m.insert(std::pair<double,string>(73.03261,"TA9318"));
    m.insert(std::pair<double,string>(93.43567,"CRP5285"));

    cout << "size: " << m.size() << endl;

    map<double, string>::iterator it;

    for (it = m.begin(); it != m.end(); it++) {
        cout  << it->first << " : " << it->second << endl;
    }

    it = m.end();
    cout << "last element is: " << it->first << " : " << it->second << endl;

return 0;
}

给我一个输出:

size: 4
69.8357 : ZRE5265
73.0326 : TA9318
79.4357 : ARH1265
93.4357 : CRP5285
last element is: 1.97626e-323 : ARH1265

当我期望得到:

size: 4
69.8357 : ZRE5265
73.0326 : TA9318
79.4357 : ARH1265
93.4357 : CRP5285
last element is: 93.4357 : CRP5285

为什么我没有得到预期的结果?

end() 为您提供了一个超过容器末尾的迭代器。这意味着只要地图不为空,最后一个有效的迭代器就是 end() - 1 。将代码更改为

it = std::prev(m.end());

将为您提供地图中的最后一个元素。

CONTAINER::end() 不指向容器中的最后一个元素,而是指向最后一个元素 之后 的元素 - 标记值。这就是为什么你的输出是一些垃圾值;你只是在随机搜索一段内存

来自std::map::end

Returns an iterator to the element following the last element of the container. This element acts as a placeholder; attempting to access it results in undefined behavior.

或者,使用 std::map::rbegin() 迭代器。它指向非反转映射的最后一个元素:

auto it = m.rbegin();

或:

auto it = std::rbegin(m);

如果您有可用的提升,我们可以很好地检查空地图并采取适当的措施:

#include <map>
#include <iostream>

#include <boost/optional.hpp>


template<class K, class V, class C, class A>
auto last_item(std::map<K, V, C, A> const& m) 
-> 
boost::optional<typename std::map<K, V, C, A>::value_type const&>
{
    boost::optional<typename std::map<K, V, C, A>::value_type const&> result;

    if (!m.empty())
    {
        result = *std::prev(std::end(m));
    }

    return result;
}

int main(void)
{

    std::map<double, std::string> m;

    m.insert(std::pair<double,std::string>(79.43567,"ARH1265"));
    m.insert(std::pair<double,std::string>(69.83569,"ZRE5265"));
    m.insert(std::pair<double,std::string>(73.03261,"TA9318"));
    m.insert(std::pair<double,std::string>(93.43567,"CRP5285"));

    std::cout << "size: " << m.size() << std::endl;

    std::map<double, std::string>::iterator it;

    for (it = m.begin(); it != m.end(); it++) {
        std::cout  << it->first << " : " << it->second << std::endl;
    }


    if (auto opt_last = last_item(m))
    {
        std::cout << "last element is: " << opt_last->first << " : " << opt_last->second << std::endl;
    }
    else
    {
        std::cout << "the map is empty\n";
    }

    return 0;
}

不幸的是,即使使用 c++17 我们也不能为此使用 std::optional,因为 std::optional 不支持可选引用。