将 map<string, int> 转换为 void* 并返回并获取密钥

convert map<string, int> to void* and back and get keys

我正在尝试使用 reinterpret_cast 将映射指针投射到 void *,然后使用 static_cast

将其投射回去

现在我在将 void * 转换回 map<string, int> *

后尝试获取存储在地图中的值时遇到问题

我尝试使用基于范围的循环和迭代器,但我似乎无法找到获取键的方法,每次我尝试访问映射值时都会出现分段错误。

这是我的代码的一个小例子:

auto *map_pointer = new map<string, int>;

for (const auto &entry : array){
    if (map_pointer->find(entry) == map_pointer->end()) {
        map_pointer->at(entry) = 1;
    } else {
        map_pointer->at(entry)++;
    }
}

void *test = reinterpret_cast<void *>(map_pointer);
auto foo = static_cast<std::map<std::string, int> *>(test);

如果可能的话,我需要找到一种方法来检索地图的键以从中取回值。
现在我不知道导致分段错误的问题是在转换为 void * 并返回时还是在我尝试使用迭代器或循环取回密钥时发生错误。

  • 关于指针转换 - 正如 StoryTeller 指出的那样 - 您可以在需要时将地图指针分配给 void*static_cast
  • 关于段错误,您为映射中未找到的键调用 at,结果为 std::out_of_range

您更正后的代码可能类似于以下内容:

std::map<int, int> m = {{0, 8}, {1, 9}, {2, 32}};
std::vector<int> arr = {0, 3, 2};

for (const auto &entry : arr){
    if (m.find(entry) == m.end()) {
        m.insert({entry, 1});
    } else {
        m[entry]++;
    }
}    

void *mp = &m;    
std::map<int, int> *m2 = static_cast<std::map<int, int>*>(mp);

for (const auto& i : *m2) {
    std::cout << i.first << ":" << i.second << "\n";
}

正在打印 0:9 1:9 2:33 3:1。参见 demo on coliru

我的经验法则是:

  • 当你用 static_cast 施放时,用 static_cast
  • 施放
  • 当你用 reinterpret_cast 施放时,用 reinterpret_cast
  • 施放
  • 如果您打算转换一个值然后使用转换后的值,请不要使用reinterpret_cast
  • 当转换是 well-known/trivial 时,使用 C 或 ctor 风格的转换是可以接受的,例如 std::string{"Hello, world"}

在这里申请,我会说"use reinterpret_cast both ways"。

为避免条目不存在时抛出异常,正确的循环代码是这样的:

for (const auto &entry : array){
    ++(*map_pointer)[entry];
}

您确定您看到的不仅仅是导致 abort() 的未处理异常吗?