【问题标题】:Obtaining smallest key in a std::map获取 std::map 中的最小键
【发布时间】:2026-01-08 15:50:01
【问题描述】:

我需要获取std::map 中的最小元素。我知道有很多可用的文档;但是,我似乎无法工作。

我有两个映射,bidask,它们都是 Book 类的属性。每个都是队列地图。这些队列中的每一个都包含Order 对象(具有各种属性,例如pricevolume 等)。我有一个成员函数update,它获得了最佳买价、最佳卖价和点差:

void update(void)
{
  unsigned long long highest_bid, lowest_ask = 0;

  for (std::map<unsigned long long, queue<Order>>::iterator it = this->bid.begin(); it != this->bid.end(); ++it)
  { 
    highest_bid = it->first;
  }

  // best ask code here

  this->bestBid = highest_bid;
  this->bestAsk = lowest_ask;
  this->spread = labs(this->bestAsk - this->bestBid);
}

询问代码在哪里,我尝试了以下方法:

lowest_ask = this->ask.begin()->first;

这可以编译,但是当我调试它时会引发断言失败(我已经阅读了这里的其他问题,但似乎无法理解):

Expression: map/set iterator not dereferencable

我尝试过反向迭代:

for(std::map<unsigned long long, queue<Order>>::reverse_iterator rit = this->ask.rbegin(); rit != this->ask.rend(); ++rit)
{
  lowest_ask = rit->first;
}

编译和调试都很好,但lowest_ask 始终为0,这是错误的。当我在调试器中单步执行它时,它不会停止,直到它达到零。

我尝试过交换迭代器:

for(std::map<unsigned long long, queue<Order>>::reverse_iterator rit = this->ask.rend(); rit != this->ask.rbegin(); ++rit)
{
  lowest_ask = rit->first;
}

这编译正常,但再次抛出调试断言失败。

我可以继续我已经尝试过的内容,但是这个问题已经过于复杂了。我只是不明白为什么我不能像一开始那样做 (lowest_ask = this-&gt;ask.begin()-&gt;first)。

非常感谢您。

【问题讨论】:

  • 我在这个循环中看不到任何意义 for (std::map>::iterator it = this->bid.begin(); it != this->bid.end(); ++it) {highest_bid = it->first;你能解释一下这个循环的意义吗?
  • 您确定您的询问地图不为空吗?
  • 从头开始std::map&lt;unsigned long long, queue&lt;Order&gt;&gt;::iterator 放入auto。这就是 C++11 的魅力。

标签: c++ c++11 map lob


【解决方案1】:

遍历地图并始终分配相同的变量似乎是不必要的辛苦工作。

如果您需要访问地图中的第一项(或地图中的最后一项),则只需 begin()(或 rbegin())即可。

    std::map <int, int> themap;

    themap[4] = 1;
    themap[2] = 2;
    themap[1] = 3;
    themap[6] = 4;
    themap[5] = 5;
    themap[7] = 6;

    if (!themap.empty())
    {
        std::cout << "item[" << themap.begin()->first << "] = " << themap.begin()->second << std::endl;
        std::cout << "item[" << themap.rbegin()->first << "] = " << themap.rbegin()->second << std::endl;
    }

您需要小心 begin 和 rbegin 的唯一时间是当您的地图为空时

【讨论】:

    【解决方案2】:

    我认为您可能只需要检查您的容器是否为空,以便 begin()rbegin() 返回有意义的内容(已定义)

    试试这个:

    void update(void)
    {
        if(bid.empty() || ask.empty())
            return;
    
        // best ask code here
    
        this->bestBid = bid.rbegin()->first;
        this->bestAsk = ask.begin()->first;
        this->spread = labs(this->bestAsk - this->bestBid);
    }
    

    【讨论】:

    • 这段代码编译得很好,但是this-&gt;bestAsk在程序结束时总是等于0,这意味着this-&gt;spread总是等于this-&gt;bestBid。即使我知道最好的询问(即在 this-&gt;ask 中对应值的最低键)不是 0。
    • @pingwing 那么很可能问题不在于获取 bestBid 和 bestAsk 的代码,而在于首先创建地图的代码。问题描述中省略了这个,但您能否包含相关代码。
    【解决方案3】:

    这并不“复杂”;它只需要一些标准的调试措施

    #include <map>
    #include <iostream>
    #include <algorithm>
    #include <random>
    #include <string>
    #include <queue>
    
    
    namespace mock {
        using Order = std::string;
    
    
        struct Book {
            using key_type = unsigned long long;  
            using order_queue_type = std::queue<Order>;        
            using property_type = std::map<key_type, order_queue_type>; 
    
            property_type bids, asks;
    
    
            void diagnose(const property_type& prop) {
                for (auto it = prop.cbegin(); it != prop.cend(); ++it) {
                    std::clog << "\t" << it->first << '\n';
                }
            }
    
            void diagnose() { 
                std::clog << "bids:" << '\n';     
                diagnose(bids);
                std::clog << "asks:" << '\n';     
                diagnose(asks);
            } 
    
            Book() {
                std::random_device rd;
                std::mt19937 gen(rd());
                std::uniform_int_distribution<key_type> ba_dist(0, 1000);
                std::uniform_int_distribution<std::size_t> len_dist(0, 10);
    
                auto prop_gen = [&] (property_type& prop) {
                    auto count = len_dist(gen);
                    for (std::size_t i = 0; i < count; ++i) {
                        auto val = ba_dist(gen);
                        auto pair = prop.emplace(val, order_queue_type());
                        if (!pair.second) {
                            std::clog << val << " already present" << '\n';
                        }
                    }
                };
    
                prop_gen(bids);
                prop_gen(asks);
            }
        };
    }
    
    
    int main() {
        mock::Book book; 
        book.diagnose();
    }    
    

    当然,不要使用我的 Book ctor 中的生成器,而是使用您的 init 例程和您的 Order 类型。

    【讨论】:

      最近更新 更多