std::map 的 const_cast 问题
我最近遇到了一个问题,我能想到的避免它的唯一方法是使用 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 中,并且由于各种其他原因它不能 <代码>地图map
,因为一些非常量函数仍然需要修改Nu内部的_m。当然,我也可以将所有这些 Nu 存储在另一个 std::vector 中,然后将映射类型切换为 const - 但这引入了一个完全不必要的向量。因此,我目前想到的唯一替代方案是在 F 函数内使用 const_cast (这应该是安全的 const_cast),我想知道这是否可以避免。
经过一番寻找之后,这个完全相同的问题已经在这里得到解决: Calling map::find带有 const 参数
I recently hit a problem and the only way I can see to avoid it is to use const_cast - but I'm guessing there is a way I'm not thinking of to avoid this without otherwise changing the function of the code. The code snippet below distills my problem into a very simple example.
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;
};
Here, suppose Nu is actually a very large struct whose layout is already fixed by the need to match an external library (and thus the "float" can't simply be folded into Nu, and for various other reasons it can't be map<Nu, float>
). The G struct has a map that it uses to hold all the Nu's it creates (and ultimately to delete them all on destruction). As written, the function F will not compile - it cannot cast (const Nu *n) to (Nu n) as expected by std::map. However, the map can't be switched to map<const Nu*, float>
because some non-const functions still need to modify the Nu's inside _m. Of course, I could alternatively store all these Nu's in an additional std::vector and then switch the map type to be const - but this introduces a vector that should be entirely unnecessary. So the only alternative I've thought of at the moment is to use const_cast inside the F function (which should be a safe const_cast) and I'm wondering if this is avoidable.
After a bit more hunting this exact same problem has already been addressed here: Calling map::find with a const argument
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是因为
map
需要Nu* const
,但您给了它一个const Nu*
。我也觉得这很不合逻辑,也不明白为什么,但事实就是这样。This is because the
map
expectsNu* const
, but you have given it aconst Nu*
. I also find it highly illogical and don't understand why, but this is how it is.在你的情况下“find”将返回一个const_iterator。推杆:
我认为应该有效。
由于您处于 const 方法中,因此您当然只能读取地图,而不能写入/修改它
"find" in your case will return a const_iterator. putting:
should work I think.
Since you are in a const method you can only read your map of course, not write/modify it