【问题标题】:map<string, int> throws std::out_of_range when called from const function [closed]map<string, int> 从 const 函数调用时抛出 std::out_of_range [关闭]
【发布时间】:2016-05-08 06:52:29
【问题描述】:

从不改变其对象状态的函数中使用 std::map 时注意到一种特殊行为:

std::map<std::string, int> _attribLocations;
...
int ProgramInfo::getAttribLocation(const std::string& name) const
{
    return _attribLocations.at(name);
}

当我调用这个函数时,传递一个字符串文字,查找抛出 out_of_range 异常:

auto index = info.getAttribLocation("v_position");

我注意到 at() 有两个版本,一个使用 const_iterator,一个不使用:

mapped_type& at(const key_type& _Keyval)
        {   // find element matching _Keyval
        iterator _Where = _Mybase::lower_bound(_Keyval);
        if (_Where == _Mybase::end()
            || _Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode())))
            _Xout_of_range("invalid map<K, T> key");
        return (_Where->second);
        }

    const mapped_type& at(const key_type& _Keyval) const
        {   // find element matching _Keyval
        const_iterator _Where = _Mybase::lower_bound(_Keyval);
        if (_Where == _Mybase::end()
            || _Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode())))
            _Xout_of_range("invalid map<K, T> key");
        return (_Where->second);
        }
    };

似乎导致它抛出的部分是:

_Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode()))

我并没有真正调试过比这更深的东西。

我正在使用 Visual Studio 2015。

我确信正在传递的密钥确实存在于地图中(通过使用调试器检查地图)。可能是地图实现中的错误,或者我错过了比较字符串的一些内容?

【问题讨论】:

  • 我正在使用 VS2015 Update 2,无法重现此行为。您是否尝试过在一个最小的示例项目中重现它?
  • 你必须告诉我们MCVE
  • 没关系,我很笨。

标签: c++ string c++11 constants stdmap


【解决方案1】:

啊,愚蠢的错误!事实证明,存储在我的地图中的键是用终止字符填充的(它们有数千个字符长,大部分是 '\0')。我传递了像“gl_position”这样的字符串文字,而查找实际上没有找到任何东西。我在非常量函数中使用了 [] 运算符,它返回默认的 int (0),这是我所期待的。但 at() 未能找到值,并抛出。这是发生了什么:

class A
{
public:

    A()
    {
        char* foo = (char*)malloc(40000);
        foo[0] = 'f';
        foo[1] = 'o';
        foo[2] = 'o';       

        for (int i = 3; i < 40000; i++)
            foo[i] = '\0';

        std::string fooStr(foo, 40000);

        map[fooStr] = 5;
    }


    int getAttribLocation(const std::string name) 
    {
        return map[name];
    }

private:
    std::map<std::string, int> map;
};

int main()
{
    A instance;

    auto x = instance.getAttribLocation("foo");
    return 0;
}

混淆来自于 [] 和 at() 之间的切换,因为我不能在常量函数中使用 []。

【讨论】:

  • 你明白你可以通过std::string fooStr(foo); 来解决这个问题,对吧?也就是说,不要将长度参数传递给构造函数。
  • 啊,是的,这比手动修剪要好。
猜你喜欢
  • 1970-01-01
  • 2015-11-25
  • 2023-03-21
  • 2016-08-28
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 2015-07-18
相关资源
最近更新 更多