2017-10-08 1 views
0

Ich versuche, den maximalen Wert eines std::map zurückzugeben.Warum kann der C++ - Compiler nicht kompiliert werden, wenn in einem Parameter kein const verwendet wird?

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; 
} 

Wenn ich pred wie folgt definieren, es funktioniert:

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

Während dies nicht funktioniert:

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

Ich verstehe nicht, warum const es erlaubt zu arbeiten.

+2

Ändern Sie die Parameter in 'pair &' und versuchen Sie es erneut. Der Kartenschlüssel ist offensichtlich ein "const". Sie können den Schlüssel eines bestimmten Werts in der Karte natürlich nicht ändern. –

+0

Yah, aber ich versuche nichts zu ändern. Warum brauche ich die Konstante? – sbryan1

+0

Sie brauchen die const, weil Sie in keinem Teil des Programms const legal cast oder konvertieren können. das heißt const Korrektheit, in C++ gehört es zur Typensicherheit. Wenn Sie versuchen, const-Objekte an eine Funktion zu übergeben, die eine nicht konstante Referenz verwendet, ist dies ein Kompilierungsfehler. const-Objekte können nicht an nicht konstante Referenzen gebunden werden. –

Antwort

0

Der Wert Typ std::map<K, V> ist nicht std::pair<K, V> sondern std::pair<K const, V>: Sie nicht den Schlüssel eines Elements des std::map<K, V> ändern können. Sie sollten den korrekten Wert Typ für die Argumente Ihrer pred() Funktion:

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

oder vorzugsweise

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

Ihre pred() Funktion die Argumente nicht ändert. Entsprechend kann und soll es wohl auch die Argumente von const& nehmen, die die Verwendung eines std::map<K, V> const erlauben. Wenn Sie die Funktion jedoch nur mit einer anderen Karte verwenden, ist dies nicht erforderlich, vorausgesetzt, sie verwendet den richtigen Werttyp.

Da std::pair hat einen Konvertierungsoperator von anderen std::pair Typen kann es [implizit] std::pair<int const, int>-std::pair<int, int> konvertieren. Das Ergebnis ist jedoch eine temporäre std::pair<int, int>, die nicht an eine nicht const Referenz gebunden werden kann. Für ein Paar von int Werten gibt es wahrscheinlich keine großen Leistungsunterschiede, aber die implizite Konvertierung kann leicht ein schwerwiegendes Leistungsproblem sein, z. B. wenn der Schlüssel oder der Wert einen Container irgendeiner Form enthält.

+0

Ok danke. Das war klar. Wo sonst können diese "impliziten" Umwandlungen gesehen werden, in denen es notwendig ist, ein "const" zu verwenden, unabhängig davon, ob ich tatsächlich beabsichtige, den Wert zu ändern. – sbryan1

+0

@ sbryan1: Der "value_type" der verschiedenen assoziativen Container ist der bekannteste Fall, den ich kenne. Es gibt wahrscheinlich andere Fälle, in denen 'Tupel'-ähnliche Typen ein Element enthalten, das möglicherweise nicht genau mit dem Typ übereinstimmt, mit dem es verwendet wird. Wenn Sie zum Beispiel ein 'std :: tuple ' einem 'std :: tuple ' zuweisen, erhalten Sie eine ähnliche Konvertierung, die ein temporäres ergibt. BTW, die Währung auf Stackoverflow ist nicht "Danke", sondern akzeptiert Antworten, möglicherweise auch, wenn Sie sie für anständig halten. –

Verwandte Themen