2011-04-19 47 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*。我也發現它非常不合邏輯,不明白爲什麼,但這是事實。