2010-03-26 38 views
11

從Visual Studio 2010開始,遍歷集合似乎會返回一個將數據作爲「常量數據」而不是非常量進行解引用的迭代器。當從Visual Studio 2010開始取消引用迭代器時的const引用從Visual Studio 2010開始

下面的代碼是一些在Visual Studio 2005上編譯但不在2010上的例子(這是一個人爲的例子,但清楚地說明了我們在自己的代碼中發現的問題)。

在這個例子中,我有一個類與溫度一起存儲位置。我定義了比較運算符(並非全部,僅足以說明問題),只使用位置而不是溫度。重點是對於我來說,如果位置相同,兩個實例是相同的;我不在乎溫度。

#include <set> 

class DataPoint 
    { 
    public: 
     DataPoint (int x, int y) : m_x(x), m_y(y), m_temperature(0) {} 
     void setTemperature(double t) {m_temperature = t;} 
     bool operator<(const DataPoint& rhs) const 
     { 
     if (m_x==rhs.m_x) return m_y<rhs.m_y; 
     else    return m_x<rhs.m_x; 
     } 
     bool operator==(const DataPoint& rhs) const 
     { 
     if (m_x!=rhs.m_x) return false; 
     if (m_y!=rhs.m_y) return false; 
     return true; 
     } 
    private: 
     int m_x; 
     int m_y; 
     double m_temperature; 
    }; 

typedef std::set<DataPoint> DataPointCollection; 

void main(void) 
{ 
DataPointCollection points; 

points.insert (DataPoint(1,1)); 
points.insert (DataPoint(1,1)); 
points.insert (DataPoint(1,2)); 
points.insert (DataPoint(1,3)); 
points.insert (DataPoint(1,1)); 

for (DataPointCollection::iterator it=points.begin();it!=points.end();++it) 
    { 
    DataPoint &point = *it; 
    point.setTemperature(10); 
    } 
} 

在主例程中,我有一個集合,我添加了一些要點。爲了檢查比較運算符的正確性,我多次添加具有相同位置的數據點。當寫出集合的內容時,我可以清楚地看到集合中只有3個點。

for循環遍歷該集合,並設置溫度。邏輯上這是允許的,因爲比較操作員沒有使用溫度。

此代碼正確編譯在Visual Studio 2005,但下面的行給出了Visual Studio 2010的編譯錯誤(在for循環):

DataPoint &point = *it; 

給出的錯誤在於,它無法分配一個「const數據點」指向[非常量]「DataPoint &」。

如果您有比較運算符只比較數據成員的某些部分,那麼在VS2010中似乎沒有像樣的(非骯髒的)代碼編寫方式。

可能的解決方案是:

  • 添加一個常量播到它給出了一個錯誤
  • 進行溫度可變的線,使setTemperature一個const方法

但對我來說這兩種解決方案看起來相當「髒」。

看起來C++標準委員會忽視了這種情況。或不?

什麼是乾淨的解決方案來解決這個問題? 你們有沒有遇到同樣的問題,你是如何解決它的?

帕特里克

+1

http://connect.microsoft.com/VisualStudio/feedback/details/532300/std-set-t-iterator-and-std-set-t-const-iterator-are-the-同類型中斷碼 – mlvljr 2012-05-10 12:43:10

+1

尼斯鏈接。似乎我不是唯一一個找到它的人。 – Patrick 2012-05-10 14:09:16

+0

是的,我只是寫了一些(現在很清楚)錯誤的STL ::設置代碼,經過一小時的調試,這就是谷歌搜索,來到這裏和那裏:) – mlvljr 2012-05-10 21:11:06

回答

13

迭代器應該給你一個const引用(這就是標準說,它應該做的),因爲改變所提及的事情會破壞集的基礎數據結構的有效性 - 一組沒有按」 t「知道」你正在改變的領域實際上並不是關鍵的一部分。替代方法是通過刪除和重新添加來進行更改,或者使用std :: map來代替。

+0

如果發現這個問題,同事。就個人而言,我會使用std :: map,但對我來說,它看起來像自定義比較運算符和集合在VS2010中不太合適。 – Patrick 2010-03-26 12:29:01

+4

自定義比較和集合只是很好,但可變數據類型和集合不。 – 2010-03-26 12:30:19

0

如果你不想刪除和重新添加,因爲尼爾建議你可以製作setTemperatureconstm_temperaturemutable

+0

正是我在我的問題中所說的。雖然這有效,但我仍然不覺得這是一個體面的解決方案。 – Patrick 2010-03-26 15:23:31

0

Set應該返回一個const迭代器,因爲它不知道任何成員函數是否可以改變順序。

看起來你真的想要一張地圖,在那裏你將你的不可變(x,y)鍵映射到一個變化的溫度。

1

剛剛開始我們轉換到2010年,這是我們一直面臨的最大障礙。幸運的是,他們確實揭示了一些長期存在的問題,我們正在改變組成排序組合的一部分。

在其他情況下,我們的解決方案是使用mutable和declare方法作爲const。當通過引用(指針或引用)將解引用的迭代器傳遞給一個函數時,如果它沒有被改變,我們將該參數作爲consst。

丹尼斯

相關問題