为什么C++编译器在参数中不使用const时编译失败?

问题描述:

我正在尝试返回std::map的最大值。为什么C++编译器在参数中不使用const时编译失败?

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 &',然后重试。显然,map键是一个'const'。显然,您不能在地图上更改某个特定值的密钥。 –

+0

是的,但我不想改变任何东西。为什么我需要const? – sbryan1

+0

您需要const,因为您无法在程序的任何部分合法地转换或转换const。这就是所谓的const正确性,在C++中它是类型安全的一部分。如果您尝试将const事传递给一个采用非const引用的函数,那么这是一个编译错误。 const的东西不能绑定到非const引用。 –

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'是我知道的最常见的情况。在其他情况下,类元组类型包含的成员可能与它所使用的类型不完全匹配。例如,将'std :: tuple '分配给'std :: tuple '时,你会得到一个类似的转换,产生一个临时的。 顺便说一句,在*的货币不是“谢谢”,但接受答案,如果你认为他们是体面的,也可能投票。 –