【1】復現問題
為了更精確的分析,先用最簡單的示例復現此錯誤場景,代碼如下:
1 #include <map> 2 #include <string> 3 4 struct Section 5 { 6 int id; 7 std::string code; 8 9 bool operator<(const Section& rhs) 10 { 11 return id < rhs.id; 12 } 13 }; 14 15 int main() 16 { 17 std::map<Section, std::string> stdMap; 18 stdMap.insert(std::make_pair(Section{ 1 }, "kaizen1")); 19 stdMap.insert(std::make_pair(Section{ 2 }, "kaizen2")); 20 stdMap.insert(std::make_pair(Section{ 3 }, "kaizen3")); 21 22 return 0; 23 }
編譯結果:
如上,穩定重現。
【2】分析原因
如上示例,你可能會問,明顯已經實現了運算符<的重載,為什么還編譯錯誤呢?
注意仔細分析錯誤提示內容,從"const_Ty"字樣不難看出編譯器需要const支持。
編譯器限定,運算符“<”內部只需讀取對象成員變量,體現出大小比較的原則即可,禁止對成員變量進行修改。
所以,重載運算符“<”的實現必須要求const限定。
【3】解決方案
方案一:重載運算符“<”
方案二:友元函數
為了便於對比,兩種方案代碼放在一起,如下示例:
1 #include <map> 2 #include <string> 3 4 struct Section 5 { 6 int id; 7 std::string code; 8 9 #if 1 10 // 方案一:重載運算符< 11 bool operator<(const Section & rhs) const // 注意:第二個const 12 { 13 return id < rhs.id; 14 } 15 #else 16 // 方案二:提供運算符<的友元函數 17 friend bool operator<(Section const& lhs, Section const& rhs) 18 { 19 return lhs.id < rhs.id; 20 } 21 #endif 22 }; 23 24 int main() 25 { 26 std::map<Section, std::string> stdMap; 27 stdMap.insert(std::make_pair(Section{ 1 }, "kaizen1")); 28 stdMap.insert(std::make_pair(Section{ 2 }, "kaizen2")); 29 stdMap.insert(std::make_pair(Section{ 3 }, "kaizen3")); 30 31 return 0; 32 }
方案一、第11行:兩個const作用說明:
(1)函數加上const后綴作用是限定函數內部實現對類成員變量具有只讀權限。
(2)形參類型加上const,限定在這個函數內部對用來進行比較的“原版對象”成員做任何修改。
對於const的和非const的實參,函數都可以使用;如果不加,就只能接受非const的實參。
另外補充,引用的作用避免在函數調用時對實參的一次拷貝,提高了效率。
備注:關於const關鍵字,建議參見隨筆《const關鍵字》
方案二、參見隨筆《友元》理解。
【4】觸類旁通
如果是std::vector容器中存儲自定義類型,又會有什么約束呢?
詳情參見隨筆《ERROR:2676》
good good study, day day up.
順序 選擇 循環 總結