我最近遇到了一个问题,我可以看到避免它的唯一方法是使用const_cast - 但我猜想有一种方法,我没有想到避免这种情况改变代码的功能。下面的代码片段将我的问题提炼成一个非常简单的例子。const_cast问题与std :: map
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;
};
这里,假设努实际上是一个非常大的结构体,其布局已经被需要匹配外部库(以及因此的“浮动”固定不能简单地被折叠成努,以及用于各种其它原因不能是map<Nu, float>
)。 G结构有一张地图,它用来保存它创建的所有Nu(最终在销毁时全部删除它们)。正如所写的,函数F不会编译 - 它不能像std :: map所期望的那样强制转换(Nu Nu * n)到(Nu n)。但是,映射无法切换到map<const Nu*, float>
,因为一些非const函数仍然需要修改Nu的内部_m。当然,我可以将所有这些Nu都存储在一个额外的std :: vector中,然后将地图类型切换为const - 但这会引入一个完全不必要的向量。所以我现在想到的唯一选择是在F函数中使用const_cast(它应该是一个安全的const_cast),我想知道这是否可以避免。
更多的狩猎后此相同的问题已经在此解决:Calling map::find with a const argument
我的C++知识不好,或者你的变量声明对我没有意义。在那里做关键字“auto”是什么? – 2011-04-19 22:09:41
如果“一些非const函数仍然需要修改Nu的内部_m”,那么Nu不能用作映射关键字。一旦它被修改,地图不再被排序。 – Cubbi 2011-04-19 22:10:27
@Joris,'auto'是C++ 0x的新特性 - 也许有些编译器已经支持它了? – 2011-04-19 22:14:39