2017-10-08 23 views
0

std::mapの最大値を返そうとしています。パラメータでconstを使用しないときにC++コンパイラがコンパイルに失敗するのはなぜですか?

int main() { 
    int N; 
    cin >> N; 
    map<int,int > m; 
    while(N--) { 
     int x; cin >> x; 
     m[x]++; 
    } 
    cout << max_element(m.begin(), m.end(), pred)->first; 
    return 0; 
} 

私はこのようなpredを定義した場合、それが動作します:

bool pred(const pair<int,int>& lhs, const pair<int,int>& rhs){ 
    return lhs.second < rhs.second; 
} 

一方、これは動作しません:

bool pred(pair<int,int>& lhs, pair<int,int>& rhs){ 
    return lhs.second < rhs.second; 
} 

constはそれを動作させることができますなぜ私は理解していません。

+2

パラメータを 'pair &'に変更してもう一度やり直してください。マップキーは明らかに 'const'です。マップ上の特定の値のキーは、オンザフライで変更することはできません。 –

+0

私は何も変えようとしていません。なぜconstが必要なのですか? – sbryan1

+0

constを必要とするのは、プログラムのどの部分でもconstをキャストまたは変換できないためです。それはconstの正確さと呼ばれ、C++では型安全性の一部です。 const以外の参照を取る関数にconstを渡そうとすると、コンパイルエラーです。 constのものは非const参照にバインドできません。 –

答えて

0

std::map<K, V>の値のタイプはstd::pair<K, V>ではなく、std::pair<K const, V>です。std::map<K, V>の要素のキーは変更できません。あなたのpred()関数の引数の正しい値の型を使用する必要があります。

bool pred(std::pair<int const, int>& lhs, std::pair<int const, int>& rhs) { ... } 

または、好ましくは

bool pred(std::map<int, int>::reference lhs, std::map<int, int>::reference rhs) { ... } 

あなたpred()関数は、引数を変更しません。これに対応して、const&によって引数を取るべきであり、それはstd::map<K, V> constの使用を可能にするはずである。ただし、非constマップのみで関数を使用する場合は、正しい値の型を使用していると仮定すると不要です。

std::pairには他のstd::pairタイプの変換演算子があるため、std::pair<int const, int>からstd::pair<int, int>に[暗黙的に]変換できます。ただし、std::pair<int, int>の一時的な結果は、constの参照にバインドできません。 intの値のペアの場合、パフォーマンスの差はほとんどありませんが、暗黙的な変換は、キーや値に何らかの形式のコンテナが含まれている場合など、大きなパフォーマンス上の問題になりやすい場合があります。

+0

ありがとうございます。それは明らかだった。私が実際に値を変更しようとしているかどうかにかかわらず、 'const'を使う必要があるこれらの"暗黙的な "変換が他にどこにあるのでしょうか。 – sbryan1

+0

@ sbryan1:さまざまな連想型コンテナーの 'value_type'は私が知っている最も一般的なケースです。 'tuple'のような型には、使用されている型と正確には一致しないメンバが含まれている場合もあります。たとえば、 'std :: tuple 'を 'std :: tuple 'に割り当てると、同様の変換が行われ、一時的なものになります。 ところで、Stackoverflowの通貨は「感謝」ではなく、回答を受け入れています。 –

関連する問題