Указатели на ключи sparsepp: Меняется ли расположение клавиш? - PullRequest
0 голосов
/ 26 февраля 2019

Чтобы сэкономить память (мне нужна карта, которая сортируется по значениям и по ключам), я храню указатели (ну, на самом деле, итераторы, согласно ответу в этом ТА вопросе) наключи sparsepp в std::vector и сортировку вектора по значениям ключей на карте:

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_, но похоже, что он сместился (большинство указателей по-прежнему указывают на значения местоположения, а некоторые нет).

Что я здесь не так делаю?Я, конечно, не вставляю / стираю / ... на карту или с карты.

Редактировать: Вот пример Minimal, Complete и Verifiable.

#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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...