在为map
中的自定义键重载operator<
时,为什么参数和函数类型都需要const
?std :: map中的自定义键,重载<运算符
回答
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引用(推荐)或值采用这两个参数。
据我了解,const reference
的参数类型提供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
,其不能成为全局或非构件比较运算符
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概念。
- 1. 重载运算符<< C++;未定义的参考`std :: basic_ostream
- 2. ==运算符为std :: map定义
- 3. 重载运算符<<用于打印自定义异常
- 4. std :: setw整个运算符<<用户自定义类型
- 5. 在C++中重载<<运算符?
- 6. 重载运算符<< ostream的
- 7. 运算符重载C++ - 重载输出“<<”运算符
- 8. 重载<<运算符的std :: ostream的
- 9. 与CArchive的运算符重载<<
- 10. 重载运算符<< - 必须是二元运算符
- 11. 重载运算符<<数组
- 12. C++朋友重载运算符<<
- 13. 运算符重载C++(<<)
- 14. 重载自定义类中的ostream运算符
- 15. 重载运算符<<为集
- 16. 重载<<运算符打印出一个std :: list
- 17. 重载运算符<<和运算符!=
- 18. 重载运算符<<:不能将左值绑定到'std :: basic_ostream <char> &&'
- 19. 在C++中重载<<运算符
- 20. 的std ::向量没有可行的重载运算符[]自定义类
- 21. 运算符重载<
- 22. 重载运算符<< operator ==和operator!=
- 23. 错误:运算符中的模糊重载=在Map中<int,std :: basic_string <char>> :: Elem :: t3 = 0
- 24. std :: list的重载括号运算符
- 25. std :: shared_ptr上的重载运算符==
- 26. 重载已定义的运算符
- 27. 继承自std :: vector <T>和重载运算符[]用于自定义索引
- 28. 重载运算符<<:不能绑定'std :: basic_ostream <char>'左值为'std :: basic_ostream <char> &&'
- 29. 在C++中调用成员的重载<<运算符
- 30. ASP.net MVC自定义字符串输出重载运算符<%= h
const引用表示没有额外的参数副本,并且不能意外地在比较函数内部更改它们 – KIIV
要比较两个常量键,您需要两个常量,每个参数一个。 –
函数后面的'const'意味着该函数不会修改正在进行比较的对象 – smac89