指向sparsepp键的指针:键的位置是否改变?

时间:2019-02-26 16:32:58

标签: c++ pointers

为了节省内存(我需要一个既按值又按键排序的映射),我存储了指向以下键的指针(根据this问题的答案,实际上是迭代器) std::vector中的sparsepp,然后根据地图中的键值对向量进行排序:

size_t i = 0;
sorted_hashtable_pointer_.resize(hashtable_.size());
for (auto it = hashtable_.begin(); it != hashtable_.end(); it++)
{
    sorted_hashtable_pointer_[i] = MapKeyPointer(it);
    i++;
}

std::sort(sorted_hashtable_pointer_.begin(), sorted_hashtable_pointer_.end(), 
[](MapKeyPointer a, MapKeyPointer b) { return *a < *b; }); 

其中hashtable_sorted_hashtable_pointer_都是类的成员。

这很好用,在排序之后(以相同的方法),我检查指针(迭代器)是否现在指向正确的位置并且它们确实指向了。

但是,当我以后访问存储的指针(迭代器)时,它们不再指向正确的位置。同时,我没有触摸hashtable_,但看起来已经移动了(大多数指针仍然指向值位置,而有些则没有)。

我在这里做错了什么?我当然不会在地图上插入/删除/...。

编辑:这是一个最小,完整和可验证的示例。

#include <sparsepp/spp.h>
#include <vector>
#include <stdint.h>
#include <algorithm>
#include <iostream>

struct MyHash {
    size_t operator()(std::vector<uint8_t> vec) const 
    {   
        std::size_t seed = vec.size();
        for(auto& i : vec) {
            seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        }
        return seed;
    }
};

struct MapKeyPointer
{
  typedef spp::sparse_hash_map<std::vector<uint8_t>, std::vector<uint32_t>>::iterator iterator;
  MapKeyPointer(iterator i) : it(i) {}
  MapKeyPointer() {}
  const std::vector<uint8_t>& operator*() const { return it->first; }
  const std::vector<uint8_t>* operator->() const { return &it->first; }
  iterator it;
};

class Test 
{
    public:
    Test() : maps_(10), sorted_(10) {}

    void Init()
    {
        for (uint32_t i = 0; i < 10; i++)
        {
            maps_[i] = spp::sparse_hash_map<std::vector<uint8_t>, int, MyHash>();
            sorted_[i] = std::vector<MapKeyPointer>();

            for (uint32_t j = 0; j < 10000; j++)
            {
                const std::vector<uint8_t> key
                { 
                    (uint8_t)(std::rand() % 255),
                    (uint8_t)(std::rand() % 255),
                    (uint8_t)(std::rand() % 255),
                    (uint8_t)(std::rand() % 255),
                    (uint8_t)(std::rand() % 255),
                    (uint8_t)(std::rand() % 255)
                };

                maps_[i][key] = std::rand();
            }
        }
    }

    void Sort()
    {
        for (size_t i = 0; i < 10; i++)
        {
            sorted_[i].resize(maps_[i].size());

            size_t j = 0;
            for (auto it = maps_[i].begin(); it != maps_[i].end(); it++)
            {
                sorted_[i][j] = MapKeyPointer(it);
                j++;
            }

            std::sort(sorted_[i].begin(), sorted_[i].end(), 
                [](MapKeyPointer a, MapKeyPointer b) { return *a < *b; });
        }
    }

    void Access()
    {
        for (size_t i = 0; i < 10; i++)
        {
            for (size_t j = 0; j < sorted_[i].size(); j++)
            {
                const std::vector<uint8_t> key = *sorted_[i][j];
                std::cout << i << " " << j << " " << key.size() << std::endl;
            }
        }
    }

    private:
    std::vector<spp::sparse_hash_map<std::vector<uint8_t>, int, MyHash>> maps_;
    std::vector<std::vector<MapKeyPointer>> sorted_;
};

int main() 
{
    Test t;
    t.Init();
    t.Sort();
    t.Access();
}

0 个答案:

没有答案