web-dev-qa-db-ja.com

[]演算子がSTLマップにconstでないのはなぜですか?

質問のために考案された例:

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map[x] << std::endl
}

[]演算子は非定数なので、これはコンパイルされません。

[]構文は非常にきれいに見えるので、これは残念です。代わりに、私はこのようなことをしなければなりません:

void MyClass::MyFunction( int x ) const
{
  MyMap iter = m_map.find(x);
  std::cout << iter->second << std::endl
}

これはいつも私を悩ませてきました。 []演算子がconstでないのはなぜですか?

83
Runcible

ために std::mapおよびstd::unordered_mapoperator[]は、インデックス値が以前に存在していなかった場合にコンテナに挿入します。それは少し直感的ではありませんが、それがそうです。

失敗してデフォルト値を挿入する必要があるため、演算子はコンテナのconstインスタンスでは使用できません。

http://en.cppreference.com/w/cpp/container/map/operator_at

83
Alan

C++ 11では at() を使用してよりクリーンなバージョンを作成できるようになりました

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map.at(x) << std::endl;
}
48
Deqing

新しい読者のためのメモ。
元の質問は、STLコンテナに関するものでした(特にstd :: mapに関するものではありません)。

ほとんどのコンテナには、演算子[]のconstバージョンがあることに注意してください。
std :: mapとstd :: setにconstバージョンがないだけであり、これはそれらを実装する基本的な構造の結果です。

Std :: vectorから

reference       operator[](size_type n) 
const_reference operator[](size_type n) const 

また、2番目の例では、要素の検索に失敗したかどうかを確認する必要があります。

void MyClass::MyFunction( int x ) const
{
    MyMap iter = m_map.find(x);
    if (iter != m_map.end())
    {
        std::cout << iter->second << std::endl
    }
}
28
Martin York

Operator []はコンテナに新しい要素を挿入する可能性があるため、constメンバー関数にすることはできません。 operator []の定義は非常に単純であることに注意してください。m[k]は(*((m.insert(value_type(k、data_type())))。first))。secondと同等です。厳密に言えば、このメンバー関数は不要です。便宜のためにのみ存在します

3
Satbir

インデックス演算子は、読み取り専用のコンテナ(STL自体には実際には存在しない)に対してのみconstである必要があります。

インデックス演算子は、値を調べるためだけに使用されるのではありません。

0
Nick Bedford