const_cast issue with std::map

const_cast issue with std::map

本文关键字:std map with issue cast const      更新时间:2023-10-16

我最近遇到了一个问题,我能看到避免它的唯一方法是使用const_cast -但我猜有一种我没有想到的方法来避免这种情况,而不改变代码的功能。下面的代码片段将我的问题提炼成一个非常简单的例子。

struct Nu
{
    Nu() {v = rand();}
    int v;
};
struct G
{
    ~G()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) delete it->first;
    }
    void AddNewNu()
    {
        _m[new Nu] = 0.5f;
    }
    void ModifyAllNu()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) it->first->v++;
    }
    float F(const Nu *n) const
    {
        auto it = _m.find(n);
        // maybe do other stuff with it
        return it->second;
    }
    map<Nu*, float> _m;
};

这里,假设Nu实际上是一个非常大的结构体,其布局已经通过需要匹配外部库而固定(因此"float"不能简单地折叠到Nu中,并且由于各种其他原因,它不能是map<Nu, float>)。G结构体有一个映射,它用来保存它创建的所有Nu(并最终在销毁时将它们全部删除)。如前所述,函数F将无法编译——它不能像std::map所期望的那样将(const Nu *n)转换为(Nu n)。然而,映射不能切换到map<const Nu*, float>,因为一些非const函数仍然需要修改_m内部的Nu。当然,我也可以将所有这些Nu存储在一个额外的std::vector中,然后将映射类型转换为const——但这会引入一个完全不必要的vector。因此,目前我想到的唯一替代方案是在F函数中使用const_cast(这应该是一个安全的const_cast),我想知道这是否可以避免。

经过更多的搜索之后,这里已经解决了这个完全相同的问题:使用const参数调用map::find

这是因为map期望Nu* const,但您给了它一个const Nu*。我也发现这是非常不合逻辑的,不明白为什么,但这就是它。

在你的例子中"find"将返回一个const_iterator。把:

map<Nu*,float>::const_iterator it = _m.find(n);
...
return it->second;

应该可以。

由于是在const方法中,所以只能读取映射,当然不能写入/修改它