Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以';用std::无序映射替换std::map_C++_Stl_C++11_Unordered Map - Fatal编程技术网

C++ 为什么可以';用std::无序映射替换std::map

C++ 为什么可以';用std::无序映射替换std::map,c++,stl,c++11,unordered-map,C++,Stl,C++11,Unordered Map,这个问题可能有点粗略,因为我家里没有可用的代码,但我知道这件事会让我整个周末都感到困扰 当我尝试将一些代码更新到C++11时,我开始用std::unordered_map替换一些std::map。代码仅使用std::map::find()访问映射中的特定元素,因此我认为替换应该很容易。返回的迭代器存储在一个auto类型的变量(auto res=map.find(x))中,因此键入的内容应该检查正常。但是,当使用res->second.do\u stuff()访问存储的元素时我得到一个编译器错误,

这个问题可能有点粗略,因为我家里没有可用的代码,但我知道这件事会让我整个周末都感到困扰

当我尝试将一些代码更新到C++11时,我开始用
std::unordered_map
替换一些
std::map
。代码仅使用
std::map::find()
访问映射中的特定元素,因此我认为替换应该很容易。返回的迭代器存储在一个
auto
类型的变量(
auto res=map.find(x)
)中,因此键入的内容应该检查正常。但是,当使用
res->second.do\u stuff()访问存储的元素时
我得到一个编译器错误,告诉我,
struct std::pair没有第二个成员。
。现在这真的让我困惑,但不幸的是我没有时间进一步调查

也许这是足够的信息,所以有人可以给我一个关于这个奇怪的编译器错误的提示。或者我的理解是
std::map
std::unordered_map
应该有相同的接口,除了需要排序的部分,这是不正确的吗

编辑

正如我在这里承诺的那样,对这个问题进行更多的分析。这很可能会让某人现在更好地帮助我。正如我从注释中的提示中猜测的,这实际上不是由我访问映射中元素的位置引起的,而是由代码的其他部分引起的。我发现的原因是,我在类X中使用映射来存储指向类X的其他元素(一种树结构)的指针。然而,这似乎适用于
std::map
,但不适用于
std::unordered_map
。下面是一些非常简单的代码,说明了这个问题:

#include <stdint.h>
#include <unordered_map>
#include <map>

class Test {
  std::map<uint32_t, Test> m_map1; // Works
  std::unordered_map<uint32_t, Test> m_map; // gives error: ‘std::pair<_T1, _T2>::second’ has incomplete type
};

int main() {
  return 1;
}
#包括
#包括
#包括
课堂测试{
std::map m_map1;//有效
std::unordered_-map m_-map;//给出错误:“std::pair::second”的类型不完整
};
int main(){
返回1;
}

std::unordered_map
有效
std::unordered_map
不起作用。你知道为什么会出现这种情况,或者可以做些什么让它与
std::unordered_map
一起工作?

我想,因为std::unordered_map需要重新格式化,因此需要复制元素,类型需要完整,而map只能与指向元素的指针不会显示该问题

这里的解决方案是将无序映射到指针:

std::unordered_map<uint32_t, std::shared_ptr<Test> >. 
std::无序的地图。

在类型不完整的情况下同时使用
映射
无序映射
涉及未定义的行为:

特别是,在以下情况下,影响未定义:

[……]

-如果在实例化模板组件时将不完整类型(3.9)用作模板参数,除非该组件特别允许


接口大致相同,但您需要确保键类型是可散列的,而不仅仅是可比较的。@ildjarn:键是示例中给出的简单字符,因此它们应该易于散列。此外,在
std::unordered_map
的定义中或在我调用
fin时,也不会出现此问题d(x)
,而是在我试图访问迭代器(或者更准确地说是第二个成员
)的位置。这就是让我困惑的部分。你能提供一个展示问题的最小示例吗?你说它不起作用是什么意思?
std::unordered_map
std::map
:你的代码在我的MSVC 2010上编译得很好。是的,没错。不幸的是,我还没有时间自己写一个更详细的解释,所以我会让你知道的我相信你的信用;-)。在这一点上需要注意的另一件事是,这两行都是无效的。正如文中所解释的,STL集合从不允许不完整类型,因此代码以前是无效的,但编译器从未捕捉到这一点。这可能是其中一种情况,未定义的行为通常不会伤害你,但你不能确定。至少现在我们是安全的。这个报价来自哪里?@ RalgTangDeTykK:从标准库要求部分C++标准。我认为它是从C++98开始就存在的。如果编译器能够生成好的错误消息,而不是在这种情况下生成工作代码(不完整类型的容器),那就太好了。我们无法确保我们的代码明天能在另一个编译器/版本上运行。@Renaud:这是关于未定义行为是好是坏的更一般性讨论的一部分。有时,您并不关心将代码移植到其他平台,但利用您的实现知识做一些事情是有用的。例如,有用的
结构树{std::list children;}可以正确地使用我的工具链,但如果按照您所说的那样操作,则会失败。另一个例子是将指针投射到非POD,我知道它们的内存布局是相同的,但从技术上讲是未定义的行为。