質問
次のコードは、マップをconst
としてoperator[]
メソッドに渡すと修飾子が破棄されることを示しています。
#include <iostream>
#include <map>
#include <string>
using namespace std;
class MapWrapper {
public:
const int &get_value(const int &key) const {
return _map[key];
}
private:
map<int, int> _map;
};
int main() {
MapWrapper mw;
cout << mw.get_value(42) << endl;
return 0;
}
これは、マップアクセスで発生する可能性のある割り当てのためですか?マップアクセスを持つ関数はconstとして宣言できませんか?
MapWrapper.cpp:10: error: passing ‘const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >’ as ‘this’ argument of ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = int, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int> >]’ discards qualifiers
解決
std::map
のoperator []
はconst
として宣言されていません。その振る舞いによるものではありません:
T <!> amp; operator [](const Key <!> amp; key)
keyに相当するキーにマップされている値への参照を返し、そのようなキーがまだ存在しない場合は挿入を実行します。
その結果、関数はoperator[]
として宣言できず、マップのfind()
を使用します。
iterator
のconst_iterator
関数を使用すると、マップを変更せずにキーを検索します。
std::pair
は.first
または<=を返します>キー(.second
)とキーの両方を含む at()
値(std::out_of_range
)。
C ++ 11では、 <=> は<=>です。要素が存在しない場合、<=>とは対照的に、関数は<=>例外をスローします。
他のヒント
operator[]
のマップではconst
を使用できません。そのメソッドは_map[key]
ではないため、マップを変更できます(find
に割り当てることができます)。代わりに<=>メソッドを使用してみてください。
operator[]
にはconst修飾されたオーバーロードがないため、 const修飾関数では安全に使用できません。これはおそらく、現在のオーバーロードが、キー値を返すことと設定することの両方を目的として構築されたためです。
代わりに、次を使用できます。
VALUE = map.find(KEY)->second;
またはC ++ 11では、 at()
演算子を使用できます:
VALUE = map.at(KEY);
GCCヘッダーの新しいバージョン(私のマシンでは4.1および4.2)には、constが宣言され、キーがマップにない場合にstd :: out_of_rangeをスローする非標準メンバー関数map :: at()があります。
const mapped_type& at(const key_type& __k) const
関数のコメントの参照から、これは標準ライブラリの新しいメンバー関数として提案されているようです。
最初に、_で始まるシンボルは、言語の実装/コンパイラライター用に予約されているため、使用しないでください。 _mapが誰かのコンパイラの構文エラーになるのは非常に簡単であり、自分以外のせいにする人はいないでしょう。
アンダースコアを使用する場合は、先頭ではなく末尾に配置します。おそらく、Microsoftのコードがそれを見ているので、この間違いを犯したのでしょう。覚えておいて、彼らは独自のコンパイラを書くので、彼らはそれで逃げることができるかもしれません。それでも、それは悪い考えです。
演算子[]は参照を返すだけでなく、実際にマップにエントリを作成します。したがって、マッピングを取得するだけでなく、マッピングがない場合はマッピングを作成します。それはあなたが意図したものではありません。