const_cast issue with std::map
const_cast issue with std::map
我最近遇到了一个问题,我能看到避免它的唯一方法是使用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方法中,所以只能读取映射,当然不能写入/修改它
相关文章:
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 使用一个考虑到std::map中键值的滚动或换行的键
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将重物插入std::map
- 使用通用值初始化 std::map,不重复
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- C++:当所有条目都保证是唯一时,替代 std::map
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- C++如何创建 std::map
- 从其他容器中移动构造"std::map"
- 将 std::map::emplace 与返回 shared_ptr 的函数一起使用是否正确?
- C++中 std::map 的运行时复杂度是多少?
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 使用重载 [] 运算符返回 std::map() 的可赋值
- std::map, std::unordered_map - 缩小初始值设定项列表中的转换范围
- C++ 使用枚举类对象分配 std::map 值
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- std::map:当元素不可默认构造时创建/替换元素
- Arduino编译器和STL:使用std::vector和std::map