【问题标题】:std::map::insert infinite loop for incorrect value_typestd::map::insert 不正确 value_type 的无限循环
【发布时间】:2013-07-19 12:58:16
【问题描述】:

我最近在我刚刚编写的一些代码中遇到了一个非常愚蠢的错误。在花了一些时间查看调试器之后,我发现了一些我觉得很奇怪的东西。考虑以下不正确但微不足道的代码。

#include <map>
#include <list>

int main() {
    std::map<int, std::list<int> > myMap;
    // infinite loop, should be std::pair<int, std::list<int> >
    myMap.insert(std::pair<int, int>(4, 500000)); 

    return 0;
}

正如注释所示,insert 语句导致程序进入无限循环。造成这种情况的原因很明显,我传入了std::pair&lt;int, int&gt; 对象而不是std::pair&lt;int, std::list&lt;int&gt;&gt;。不幸的是,这段代码在 gcc 和 MSVC10 中编译得非常好。我希望编译器拒绝此代码,因为类型显然不匹配,但事实并非如此。有人愿意解释为什么吗?

编辑:它在 gcc 中似乎可以正常工作(我使用的站点无法正常工作),但 MSVC10 仍然接受它。

再次编辑:我认为崩溃的原因是,在我的原始代码中,插入是这样插入的:

myMap.insert(std::pair&lt;int, int&gt;(4, id)) 其中id 可能非常大。它从未引发任何内存异常,但我想它花费了大量时间来分配它(没有失败),这就是它出现循环的原因。因此,似乎 MSVC 很乐意将隐式转换为 std::list,但 gcc 却不是。这很令人困惑,根据http://www.cplusplus.com/reference/list/list/list/std::list 的构造函数都标记为explicit。看起来错误是 MSVC10,MSVC11 拒绝此代码(应该如此)。

【问题讨论】:

标签: c++ visual-c++ stl


【解决方案1】:

我尝试在 Visual Studio 2010 中编译

Microsoft Visual Studio 2010
Version 10.0.40219.1 SP1Rel

它编译了,但是没有进入一个无限循环。相反,它做了以下事情......

std::map<int, std::list<int> > myMap;

myMap.insert(std::pair<int, int>(4, 5)); // An implicit cast???

std::cout << "mymap now contains " << myMap.size() << " elements.\n";
std::cout << "myMap[4] size is " << myMap[4].size() << '\n';

sel = myMap[4].begin();
end = myMap[4].end();
for(; sel != end; ++sel)
    std::cout << *sel << ", ";
std::cout << std::endl;

输出以下内容

mymap now contains 1 elements.
myMap[4] size is 5
0, 0, 0, 0, 0,

所以,我认为它起作用的原因是列表是使用以下默认构造函数创建的:

explicit list (size_type n, const value_type& val = value_type(),
               const allocator_type& alloc = allocator_type());

所以它为你创建了 4 个映射到 5 个元素的列表,每个元素都用 value_type() 填充。

我的猜测是 不知何故 msvc 编译器正在使用上述列表构造函数将 std::pair&lt;int, int&gt; 转换为 std::pair&lt;int, std::list&lt;int&gt;&gt;...

这在某种程度上回答了为什么它编译时没有抱怨......但它没有解释你的无限循环......不知道该说什么:)

【讨论】:

  • 我更新了我的代码,循环是由5引起的,实际上不是5,它可能是一个相当大的数字。所以我想转换需要一段时间才能完成(因此感知到循环)。我已经更新了我的问题,但我仍然感到困惑,因为该构造函数是显式的。
  • 是的,我不确定。该列表可以用size_type 构造,所以我认为这是一个有效的显式创建列表,即构造函数的参数是正确的类型 - 例如,我们可以做std::list&lt;int&gt;(100) ......但这正在创建一个列表...这是一个演员表,所以正如你所说,它是否应该隐式创建列表?!可能不是,但它似乎确实这样做了:-S
  • 据我了解,explicit 意味着它无法对std::list 进行任何转换——您需要显式调用构造函数。我试图用 MSVC11 编译这段代码,但它被拒绝了,所以我猜这是 2010 编译器中的一个错误。
  • 我的评论不是很清楚......我的意思是如果你直接调用构造函数会很好但质疑你是否应该能够转换它,你是对的,你不应该如果它被标记为explicit,就可以做到。只是试图搜索这个和 msvc 的任何已知问题
  • 值得向 MS 留下一些反馈...也许有人会知道编译器为什么要这样做? connect.microsoft.com/VisualStudio/feedback
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 2019-04-25
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
相关资源
最近更新 更多