我最近遇到了一个问题,我唯一可以看到避免它的方法是使用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实际上是一个非常大的结构,其布局已经通过匹配外部库的需要而得到修复(因此“浮动”不能简单地折叠成Nu,并且出于各种其他原因,它可以' t是map<Nu, float>
)。 G struct有一个映射,用于保存它创建的所有Nu(并最终在销毁时删除它们)。如上所述,函数F不会编译 - 它不能像std :: map那样强制转换(const Nu * n)到(Nu n)。但是,地图无法切换到map<const Nu*, float>
,因为某些非const函数仍需要修改_m内部的Nu。当然,我可以选择将所有这些Nu 存储在一个额外的std :: vector中,然后将地图类型切换为const - 但是这会引入一个完全没必要的向量。所以我目前唯一想到的选择就是在F函数中使用const_cast(应该是一个安全的const_cast),我想知道这是否可以避免。
经过多次搜索后,这里已经解决了同样的问题:Calling map::find with a const argument
答案 0 :(得分:0)
这是因为map
期望Nu* const
,但您已经给它const Nu*
。我也发现它非常不合逻辑,不明白为什么,但事实就是这样。
答案 1 :(得分:-1)
“find”将返回一个const_iterator。把:
map<Nu*,float>::const_iterator it = _m.find(n);
...
return it->second;
我认为应该工作。
由于你是一个const方法,你当然只能阅读你的地图,而不是写/修改它