map <string,int =“”>从const函数

时间:2016-05-08 06:52:30

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

从不改变对象状态的函数中使用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.

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

1 个答案:

答案 0 :(得分:1)

啊,这个愚蠢的错误!事实证明,存储在我的地图中的密钥用终止字符填充(它们长达数千个字符,大多数是'\ 0')。我传递的字符串文字像“gl_position”,查找实际上没有找到任何东西。我在非const函数中使用了[]运算符,它返回默认的int(0),这是我期待的那个。但在()未能找到值,并投掷。以下是发生的事情:

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()之间切换,因为我无法在常量函数中使用[]。