2016-06-28 108 views
3

在为map中的自定义键重载operator<时,为什么参数和函数类型都需要conststd :: map中的自定义键,重载<运算符

+0

const引用表示没有额外的参数副本,并且不能意外地在比较函数内部更改它们 – KIIV

+0

要比较两个常量键,您需要两个常量,每个参数一个。 –

+0

函数后面的'const'意味着该函数不会修改正在进行比较的对象 – smac89

回答

1

std::map<K, V>的value_type不是您想象的std::pair<K, V>,而是实际std::pair<const K, V>因此,在键上调用的任何比较都会处理const对象。

现在,当编译器看到

a < b 

a至少一个或b是用户定义类型的,编译器调用任一

operator < (a, b); //(1) 

a.operator < (b); //(2) 

(如果这两个都可用,则出现错误d)。

一个非常量成员函数,包括任何运算符,可以在非常量对象上调用只有。因此,因为a是不变的,所以要求在//2的情况下将该函数声明为const。由于b也是常量,因此参数必须是常量引用,因为非常量引用不能绑定到常量对象。因此,这两个常量的要求。

该参数除了是const以外还有其他选项。它可以通过值来取参数,但这意味着不必要的复制。同样,如果您选择声明非成员operator <,则应该通过const引用(推荐)或值采用这两个参数。

1

原型为操作者<是

bool operator<(const Element& b) const { ..... } 

const Element& b意味着元素B的额外副本不会在所述operator<的调用创建以及参数不该方法内修改。第二个const表示调用operator<的对象在调用此调用时不会被修改。

+0

第二个'const'只是承诺比较的对象没有被修改 – smac89

+0

@ Smac89确实。感谢您指出。 – toro

+0

'operator <'有两个原型,非成员和成员之一。更常用和推荐的一个是非会员(因为太长时间无法进入此处),但您已经将会员原型引用为“原型”。 –

1

据我了解,const reference的参数类型提供2个用途:

  1. 从它告诉,参数是不可修改的内部函数体和任何这样的奇遇会产生编译器错误签名。
  2. 没有额外的不必要的key类型的复制。

成员函数由const以便你仍然可以做一个find(或任何其它纯读(除非修改mutable构件)的操作)一个const地图对象上调用。如果没有那个const,试图在const map对象上调用这些成员函数时,会导致编译错误。

当您尝试创建自定义比较函数时,不需要全局或非成员函数的const

bool operator<(const Key& a, const Key& b) /* no const required here*/ {....} 

const一个功能是只适用于成员函数,因为它使this指针或实例的const,其不能成为全局或非构件比较运算符

的情况下
0

CONST在一种说法是功能看好它的主叫方不会修改传入的参数时,参数按引用传递,以避免额外的副本,但不会修改它往往是需要的,例如:

void function(const Type& var) 
{ 
    // can't modify var here, but can read and call its const methods (see below) 
} 

方法声明中的Const是一种方法,承诺不修改它所调用的对象的内部状态。例如

void Class::function(const Type& var) const 
{ 
    // can't modify var here 
    // can't modify "this" here (call other non const methods or change member variables) 
} 

那些承诺可以被打破(这是C++中,我们所谈论的毕竟)铸造常量性了,但是这是意图反正。

总是要求尽可能少的东西是个好主意。如果方法不改变一个对象 - 声明它为const,那么你可以在该类的一个const实例上调用这个方法(例如,当它作为一个const引用传递给其他地方时)。

在std :: map上定制operator <的情况下,不能在参数中使用非const引用的原因是因为std :: map会在一个或多个自己的方法中调用你的运算符,被自己声明为const。编译器不允许它将const对象传递到不承诺不修改它的函数中。

你不能声明operator <本身非const的原因(假设它不是一个独立函数,而是你自定义类的一个方法用作键)是一样的 - std :: map已经答应不要修改密钥(这会对一个排序造成严重破坏),所以它不能调用任何不能保证不变的方法。

定制operator <当用于排序容器内部也有其他要求 - 它必须满足LessThanComparable概念。

相关问题