【问题标题】:Initializing map of maps with initializer list in VS 2013在 VS 2013 中使用初始化列表初始化地图的地图
【发布时间】:2013-10-16 15:41:07
【问题描述】:

我正在尝试使用 C++11 初始化地图地图。我的编译器是 VS 2013 Express。

unordered_map<EnumType, unordered_map<string, string>> substitutions = {
    {
        Record::BasementType,
        {
            { "0", "" },
            { "1", "Slab or pier" },
            { "2", "Crawl" }
        }
    },
    {
        Record::BuildingStyle,
        {
            { "0", "" },
            { "1", "Ranch" },
            { "2", "Raised ranch" }
        }
    },
    // ... and so on
};

它已编译,但我在 ntdll.dll 中遇到断点。但是此代码的简化版本:

unordered_map<EnumType, unordered_map<string, string>> substitutions = {
    {
        Record::BasementType,
        {
            { "0", "" },
            { "1", "Slab or pier" },
            { "2", "Crawl" }
        }
    },
    // *nothing more*
};

正常工作。

为什么当我在地图中有一对以上时这不起作用?如何做得更好?

【问题讨论】:

  • “我在 ntdll.dll 中得到断点”太模糊了。有断言吗?如果是这样,断言说明了什么。
  • 但看起来是这样,我得到了指向初始化列表末尾的断点,而后面只有反汇编。在调试模式下它是相同的,但我通过 std::pair、std::map、(反汇编)、std::_Tree 获得堆栈跟踪几次,它最终出现在文件 xtree 第 327 行:_DEBUG_ERROR("map/set iterators不兼容");
  • 好吧,那我恐怕现在也帮不上什么忙了。如果以后有时间。您可以使用一些在线编译器来查看代码是否在那里运行(例如,使用 G++ 或 Clang++)。如果是这样,它可能是一个 VS2013 错误。只看代码我看不出有什么问题。

标签: c++ c++11 stl visual-studio-2013


【解决方案1】:

这是一个已知的编译器错误,http://connect.microsoft.com/VisualStudio/feedback/details/800104/。编译器会被初始值设定项列表中的临时变量弄糊涂,甚至会反复销毁单个对象。因为这是无声的错误代码生成,我已经要求编译器团队优先解决这个问题。

【讨论】:

  • 我认为这是某种错误。谢谢!
  • 我想我遇到了同样的错误(?),函数声明为struct X { void foo(/*..........*/, std::string const&amp; data = {}); }。当使用data 默认调用时,它会随机崩溃,但并非总是如此。我是对的,这可能是同一个错误吗? [另外,是否有可能提供修补程序?]
  • 无论如何,我认为这可能是一个不同的错误。如果您有兴趣,这是最小的复制器:Question: (Known) compiler bug in VC12?
  • Stephan,目前有没有修复此错误的编译器版本?很遗憾,我不得不避免所有 {} 初始化,因为这往往会导致我的 MSVC2013 编译器出现问题
  • 我刚刚在完全更新的 MSVC2013 中遇到了这个错误(请参阅问题 stackoverflow.com/questions/33553265/…)。编译器团队显然没有优先考虑这一点。 :)
【解决方案2】:

多年来我发现的一种解决方法是在初始化列表中使用make_pair,而不是每对括号初始化器 ({ ... }):

std::unordered_map<Record, std::unordered_map<std::string, std::string>> testmap = {
    make_pair(Record::BasementType, std::unordered_map<std::string, std::string>({ { "0", "" }, { "1", "Slab or pier" }, { "2", "Crawl" } })),
    make_pair(Record::BuildingStyle, std::unordered_map<std::string, std::string>({ { "0", "" }, { "1", "Slab or pier" }, { "2", "Crawl" } })),
    // ... and so on
};

不管临时初始化器的问题如何,编译器似乎都能很好地处理这些对。

请注意,在您的情况下,您必须显式转换内部 unordered_map 初始化程序,因为它可能有多个 stl 容器类型被这样初始化。或者,您可以在 make_pair 上提供具有相同转换结果的模板类型:make_pair&lt;Record, std::unordered_map&lt;std::string, std::string&gt;&gt;(...)

也许这种解决方法可以帮助像我这样仍在使用 VS2013 的人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 2019-06-05
    • 2012-11-07
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多