web-dev-qa-db-ja.com

C ++マップアクセスが修飾子を破棄する(定数)

次のコードは、マップを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

103
cdleary

std::mapoperator []constとして宣言されておらず、その動作が原因ではありません:

T&operator [](const Key&キー)

Keyと同等のキーにマップされている値への参照を返します。そのようなキーがまだ存在しない場合は挿入を実行します。

その結果、関数はconstとして宣言できず、マップのoperator[]を使用できます。

std::mapfind() 関数を使用すると、マップを変更せずにキーを検索できます。

find() は、iterator、またはconst_iteratorstd::pair キー(.first)と値(.second)の両方を含む。

C++ 11では、std::mapat() を使用することもできます。要素が存在しない場合、std::out_of_rangeとは対照的に、関数はoperator []例外をスローします。

143
luke

_operator[]_ にはconst修飾されたオーバーロードがないため、const修飾された関数では安全に使用できません。これはおそらく、現在のオーバーロードが、キー値を返すことと設定することの両方を目的として作成されたためです。

代わりに、次を使用できます。

_VALUE = map.find(KEY)->second;
_

または、C++ 11では、 at() 演算子を使用できます。

_VALUE = map.at(KEY);
_
10
Richard

constのマップではoperator[]を使用できません。このメソッドはマップを変更できるためconstではないためです(_map[key]に割り当てることができます)。代わりにfindメソッドを使用してみてください。

10
nlativy

GCCヘッダーの新しいバージョン(私のマシンでは4.1および4.2)には、constが宣言され、キーがマップにない場合にstd :: out_of_rangeをスローする非標準メンバー関数map :: at()があります。

const mapped_type& at(const key_type& __k) const

関数のコメントの参照から、これが標準ライブラリの新しいメンバー関数として提案されているようです。

7
Nathan Kitchen

まず、_で始まるシンボルを使用しないでください。これらのシンボルは、言語の実装/コンパイラライター用に予約されています。 _mapが誰かのコンパイラの構文エラーになるのは非常に簡単であり、あなた自身のせいにする人はいません。

アンダースコアを使用する場合は、先頭ではなく末尾に配置します。おそらく、Microsoftのコードがそれを実行しているのを見て、この間違いを犯したのでしょう。覚えておいて、彼らは独自のコンパイラを書くので、彼らはそれで逃げることができるかもしれません。それでも、それは悪い考えです。

演算子[]は参照を返すだけでなく、実際にマップにエントリを作成します。したがって、マッピングを取得するだけでなく、マッピングがない場合はマッピングを作成します。それはあなたが意図したものではありません。

0
Dov