Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2621377
  • 博文数量: 315
  • 博客积分: 3901
  • 博客等级: 少校
  • 技术积分: 3640
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-08 15:32
个人简介

知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516

文章分类

全部博文(315)

文章存档

2019年(2)

2018年(1)

2016年(7)

2015年(32)

2014年(39)

2013年(109)

2012年(81)

2011年(44)

分类: C/C++

2014-02-23 22:14:50

这里我想用一系列的代码来阐述这个问题.


1:

请看如下代码:

  1. #include   
  2. #include   
  3. using namespace std;  
  4.   
  5. int main()  
  6. {  
  7.     complex<int> a(1, 2);  
  8.     mapint>, int> k;         //默认按小于排序  
  9.     //k[a] = 5;  
  10.     return 0;  
  11. }  




	

以上代码运行正常。


2:

继续看如下代码:

  1. #include   
  2. #include   
  3. using namespace std;  
  4.   
  5. int main()  
  6. {  
  7.     complex<int> a(1, 2);  
  8.     mapint>, int> k;   //在这里,complex叫做key的类型,int叫做value的类型  
  9.     k[a] = 5;                   //加入了元素  
  10.     return 0;  
  11. }  

	

以上代码出错了。

原因是: 当执行 k[a] = 5 时, 即向 k 加入了一个新的 pair, int> 型的元素,而map是会自动对元素进行排序,排序的方式是按key的大小来排序。但complex却没有定义对复数比较的函数,于是map就不知如何比较complex,最终导致编译错误。


 


3:

自以为对的扩展complex类:


  1. #include   
  2. #include   
  3. using namespace std;  
  4.   
  5. bool operator< (complex<int> l, complex<int> r)    //为complex重载小于运算符,因为map会自动排序  
  6. {  
  7.     if (l.real() < r.real()) return true;  
  8.         else return false;  
  9. }  
  10.   
  11. int main()  
  12. {  
  13.     complex<int> a(1, 2), b(3, 4);  
  14.     mapint>, int> k;           
  15.     k[a] = 5;  
  16.     return 0;  
  17. }  





	

以上编译错误。按理只要重载小于运算符(因为map默认按小于排序),就应该可以的啦,但还是编译不过。错误信息和2的一样,还是由于没找到比较complex的函数

.

3-1:

真的没找到?

  1. #include   
  2. #include   
  3. using namespace std;  
  4.   
  5. bool operator< (complex<int> l, complex<int> r)    //为complex重载小于运算符,因为map会自动排序  
  6. {  
  7.     return (l.real() < r.real());  
  8. }  
  9.   
  10. int main()  
  11. {  
  12.     complex<int> a(1, 2), b(3, 4);  
  13.     mapint>, int> k;           
  14. //  k[a] = 5;  
  15.     a < b;   //事实证明,确实重载了complex的小于比较  
  16.     return 0;  
  17. }  


	

以上代码运行正常。

以上代码编译通过。至少证明complex的小于运算符是重载成功的。但map又怎么会找不到呢?



3-2:

侧面验证:

  1. #include   
  2. using std::map;  
  3.   
  4. template <class T>  
  5. class complex  
  6. {  
  7. public:  
  8.     complex(T real){this->treal = real;}  
  9.     T real(){return treal;}  
  10. private:  
  11.     T treal;  
  12. };  
  13.   
  14.   
  15. bool operator< (complex<int> l, complex<int> r)    //为MyClass重载小于运算符,因为map会自动排序  
  16. {  
  17.     return (l.real() < r.real());  
  18. }  
  19.   
  20.   
  21. int main()  
  22. {  
  23.     mapint>, int> k;         //默认按小于排序  
  24.     complex<int> a(1);  
  25.     k[a] = 5;  
  26.     return 0;  
  27. }  


	

以上编译通过。
我自编了一个极其简陋complex类(其实只是名字一样罢了),其余没变,map似乎又找到了complex的小于运算符了。怪哉!


4:

思考:

重载的complex的小于运算符没有错。那么,请大家比较一下3和3-2,3用的是stl里的complex,3-2用的是我编的 “complex”,两者有什么根本的不同?
答:内容不同咯!
但两者都有complex的小于运算符,但在3中map又为何找不到呢?
所有的证据都指向了-------namespace std


5:
验证:

  1. #include   
  2. #include   
  3. using namespace std;  
  4.   
  5. namespace std  
  6. {  
  7.         bool operator < (complex<int> l, complex<int> r)  
  8.         {  
  9.                 return l.real() < r.real();  
  10.         }  
  11. }  
  12.   
  13.   
  14. int main()  
  15. {  
  16.         mapint> , int> k;  
  17.         complex<int> a(1,2);  
  18.         k[a] = 5;  
  19.         return 0;  
  20. }  

以上编译成功了~



6:
map/set 的 “陷阱”:
以上所有代码我虽然只用了map来测试,事实上set也一样的。
所谓陷阱,其实也只不过是一些不容易发现或者平时没留意的一些细节:
map的完整参数是这样的——map< class Key,   class T,   class Compare = less,   class Allocator = allocator< pair > >
当class  Key的域是在std中, class Compare就会自动到std中去找key的小于函数。
若class Key 的域不在std中, class Compare就会不会到std中去找key的小于函数。
即map/set是根据Key的域来寻找Key的比较函数。



7:

以上推理仅个人意见,如有不当,恳请指出。


http://blog.csdn.net/kof2001kop/article/details/6695024

阅读(3316) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~