2014-02-17 22 views
0

我正在將Visual Studio 2008 VC++項目遷移到Visual Studio 2013.遷移我的其中一個項目時出現錯誤C3892。這裏是一個重現問題的一些示例代碼:錯誤VS2013中的c3892迭代器問題

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    struct student 
    { 
     int id; 
     int marks; 
     bool changed; 

     bool operator < (const student& refParam) const 
     { 
      return false ; 
     } 
     student(int a,int b) 
     { 
      id=a; 
      marks=b; 
      changed=true; 
     } 
    }; 

    student x(10,500),y(15,600); 
    std::multiset<student> myset; 
    myset.insert(x); 
    myset.insert(y); 
    std::multiset<student>::reverse_iterator iter; 
    for (iter=myset.rbegin(); iter != myset.rend(); ++iter) 
    { 
     std::cout<<iter->id<<"\n"; 
     std::cout<<iter->marks<<"\n"; 
     std::cout<<iter->changed<<"\n"; 
     iter->changed=false; 
    } 

    return 0; 
} 

試圖編譯上面拋出Error:

error C3892: 'std::_Revranit<_RanIt,_Base>::operator ->' : you cannot assign to a variable that is const 

然而,同樣的代碼沒有錯誤編譯在Visual Studio 2008中我應該改變在我的項目中的價值?

+3

'operator <'不符合'std :: set'的嚴格弱順序要求。實現一個除了總是返回'false'之外的東西。並且在C++ 11中'set'的迭代器更改爲引用常量元素而非非常量,這會導致您的錯誤。 – WhozCraig

+0

@WhozCraig'返回std :: tie(id,mark,changed)

+1

@Joker_vD如果我需要三個人的話,我不會這樣做。 「std :: tie」就是那些貓的鬍鬚。 – WhozCraig

回答

1

C++ 11中的所有multiset迭代器都指向一個const元素。如果你想修改元素,你需要刪除它並插入一個新的元素。 作爲一種破解,你可以將struct變量聲明爲mutable(不推薦)。只有當你確定你在做什麼時才這樣做

mutable bool changed; 

另外你還應該寫一個適當的運算符<。

+0

代替使用'mutable' hack,將您的設置更改爲地圖,並將「更改」放置在可以安全進行變異的值部分中。 – StilesCrisis

-2

根據在VS2010以後實現的C++ 11標準,我們不能更改集合或多集合中的元素。默認情況下,迭代器引用一個常量元素。如果我們想改變一個集合或多集合中的元素,我們必須進行顯式類型轉換。

在上面的代碼iter->changed=false拋出一個C3892錯誤,但如果我們改變了語句

const_cast<student&>(*item).changed=false; 

相反,它將編譯沒有任何錯誤。

+1

更改集合成員很危險。 (特別是如果這會使其在設置中「失序」。) – StilesCrisis

+2

雖然這會**編譯**,但這是不對的。事實上,我很確定這是未定義的行爲。有關可能的後果,請參閱http://ideone.com/RGKdqw。 – jerry