2011-04-19 91 views
1

我最近遇到了一个问题,我可以看到避免它的唯一方法是使用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

+0

我的C++知识不好,或者你的变量声明对我没有意义。在那里做关键字“auto”是什么? – 2011-04-19 22:09:41

+3

如果“一些非const函数仍然需要修改Nu的内部_m”,那么Nu不能用作映射关键字。一旦它被修改,地图不再被排序。 – Cubbi 2011-04-19 22:10:27

+1

@Joris,'auto'是C++ 0x的新特性 - 也许有些编译器已经支持它了? – 2011-04-19 22:14:39

回答

-1

“发现”你的情况将返回一个常量性。把:

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

... 

return it->second; 

应该工作我认为。

既然你在一个const方法,你只能读你的课程地图,不写/修改

+0

不幸的是这不会编译或者 - 返回类型将被正确地推断为地图 ::为const_iterator,但.find(N)不会,因为它不能使用const怒江*投怒江匹配参数*。 – 2011-04-19 22:23:39

+0

是的,你是对的。只需将代码放在cpp文件中即可解决此问题。 – 2011-04-19 22:55:15

0

这是因为map预计Nu* const,但你给了它一个const Nu*。我也发现它非常不合逻辑,不明白为什么,但这是事实。