首页 > 技术文章 > map中左边为指针时引发的思考

dayq 2019-12-17 15:28 原文

map左边只有结构体指针时,地址分配由创建顺序由大到小,map左边排序按照指针地址数值大小由大到小进行排序,不同于平时的由小到大。

 1 #include<iostream>
 2 #include<map>
 3 using namespace std;
 4 typedef struct tree* T;
 5 struct tree{
 6     string s;
 7     T next;
 8 };
 9 int main()
10 {
11 
12     T t3=new tree();
13     cout<<"先创建t3,再创建t1,最后创建t2\n";
14     t3->s="helloaworld";
15     T t1=new tree();
16     t1->s="hello";
17     T t2=new tree();
18     t2->s="adad";
19     map<T,int> m;
20     m[t3]=7;
21     m[t2]=6;
22     m[t1]=5;
23     for(auto i:m)
24     {
25         cout<<i.first->s<<" "<<i.second<<endl;
26     }
27     cout<<"&t2="<<&t2<<endl;
28     cout<<"&t3="<<&t3<<endl;
29     cout<<"&t1="<<&t1<<endl;
30     cout<<"可见,随着先后创建顺序的不同,分配的地址空间数值变小\n";
31 }

map左边为int指针时,数组为int[]时,int指针地址随着创建的先后顺序,地址数值依次变小,但是map中排序按照地址数值从小到大。

 1 #include<iostream>
 2 #include<map>
 3 using namespace std;
 4 int main()
 5 {
 6     map<int*,int> m;
 7     int c[]={1,2,4};
 8     m[c]=4;
 9     int a[]={1,2,3,4,5};
10     m[a]=5;
11     int b[]={3,4,5,67};
12     m[b]=9;
13     cout<<"a="<<a<<endl;
14     cout<<"b="<<b<<endl;
15     cout<<"c="<<c<<endl;
16     cout<<(a>b?"a大于b":"a小于b")<<endl;
17     for(auto i:m)
18     {
19         cout<<i.first<<endl;
20     }
21     
22 }

当map左边为结构体指针时,且结构体指针有数组的情况时,结构体指针的地址由小到大,map里面排序按照地址数值由小到大

 1 #include<iostream>
 2 #include<map>
 3 using namespace std;
 4 typedef struct tree* T;
 5 struct tree{
 6     string s;
 7     T next;
 8 };
 9 int main()
10 {
11     T a=new tree[7];
12     a->s="aaa";
13     T s=new tree[5];
14     T h=new tree();
15     T b=new tree();
16     cout<<"a="<<a<<endl;
17     cout<<"s="<<s<<endl;
18     s[0].s="sss";
19     h->s="hhh";
20     b->s="bbb";
21     cout<<"h="<<h<<endl;
22     cout<<"b="<<b<<endl;
23     map<T,int> m;
24     m[a]=7;
25     m[b]=6;
26     m[s]=1;
27     m[h]=2;
28     for(auto i:m)
29     {
30         cout<<i.first->s<<" "<<i.second<<endl;
31     }
32 }

当map左边是结构体指针和普通的结构体对象时的不同

 1 //#include<iostream>
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 typedef struct tree* T;
 5 struct tree{
 6     string name;
 7     int id;
 8     T next;
 9     tree(string s,int i)
10     {
11         this->name=s;
12         this->id=i;
13     }
14     bool operator<(const tree &a)const
15     {
16         return a.name<name;
17     }
18 };
19 int main()
20 {
21     map<T,int> m;
22     T t=new tree("hello",5);/*指针类型创建对象有new*/
23     m[t]=9;
24     T f=new tree("hello",5);
25     m[f]=9;
26     for(auto i:m)
27     {
28         cout<<i.first->name<<" "<<i.first->id<<" i.second="<<i.second<<endl;
29     }
30     t->id=7;
31     m[t]=6;
32     for(auto i:m)
33     {
34         cout<<i.first->name<<" "<<i.first->id<<" i.second="<<i.second<<endl;
35     }
36     cout<<"可见,map左边为指针时,修改指针上的值,对已经存进map的数据也有修改。\n"; 
37     cout<<"以上是tree指针的map,以下是tree实体对象的map\n";
38     map<tree,int> p;
39     tree tr=tree("world",8);/* 实体对象就不用new了*/
40     p[tr]=4;
41     for(auto i:p)
42     {
43         cout<<i.first.name<<" "<<i.first.id<<" i.second="<<i.second<<endl;
44     }
45     tr.id=7;
46     p[tr]=6;
47     for(auto i:p)
48     {
49         cout<<i.first.name<<" "<<i.first.id<<" i.second="<<i.second<<endl;
50     }
51     cout<<"可见,map左边为普通的实体对象时,修改对象上的数据,对已经存进map的数据没有修改\n";
52 }

Last,map左边为具体结构体对象时,map[tree]=5;存进去的只是这个结构体当时的状态,所以,存进去以后再修改对象结构体里面的数据,对map没有影响,但仍然可以map[tree]=6,通过这样的方式来修改键值对的值。

当map左边是结构体指针的时候,map[T]存进去的是地址,等需要使用的时候,map会根据地址,找到地址上的值来输出,所以改动有效。

 1 //#include<iostream>
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 typedef struct tree* T;
 5 struct tree{
 6     string name;
 7     int id;
 8     T next;
 9     tree(string s,int i)
10     {
11         this->name=s;
12         this->id=i;
13     }
14     bool operator<(const tree &a)const
15     {
16         return a.name<name;
17     }
18 };
19 int main()
20 {
21     map<T,int> m;
22     T t=new tree("hello",5);/*指针类型创建对象有new*/
23     m[t]=9;
24     for(map<T,int>::iterator it=m.begin();it!=m.end();it++)
25     {
26         cout<<"&dizhi="<<&it->first<<endl;
27         cout<<it->first->name<<" "<<it->first->id<<" i.second="<<it->second<<endl;
28     }
29     cout<<"t="<<t<<endl;
30     t->id=7;
31     m[t]=6;
32     for(map<T,int>::iterator it=m.begin();it!=m.end();it++)
33     {
34         cout<<"&dizhi="<<&it->first<<endl;
35         cout<<it->first->name<<" "<<it->first->id<<" i.second="<<it->second<<endl;
36     }
37     /*for(auto i:m)
38     {
39         cout<<"&dizhi="<<&i.first<<endl;
40         cout<<i.first->name<<" "<<i.first->id<<" i.second="<<i.second<<endl;
41     }*/
42     /* 这里有个未解之谜,就是上面两次用auto,前后两次的i.first的地址不一样。 */
43     cout<<"t="<<t<<endl;
44     cout<<"可见,map左边为指针时,修改指针上的值,对已经存进map的数据也有修改。\n"; 
45     cout<<"以上是tree指针的map,以下是tree实体对象的map\n";
46     map<tree,int> p;
47     tree tr=tree("world",8);/* 实体对象就不用new了*/
48     p[tr]=4;
49     /*for(auto i:p)
50     {
51         cout<<"&dizhi="<<&i.first<<endl;
52         cout<<i.first.name<<" "<<i.first.id<<" i.second="<<i.second<<endl;
53     }*/
54     for(map<tree,int>::iterator it=p.begin();it!=p.end();it++)
55     {
56         cout<<"&dizhi="<<&it->first<<endl;
57         cout<<it->first.name<<" "<<it->first.id<<" i.second="<<it->second<<endl;
58     }
59     tr.id=7;
60     p[tr]=6;
61     /*for(auto i:p)
62     {
63         cout<<"&dizhi="<<&i.first<<endl;
64         cout<<i.first.name<<" "<<i.first.id<<" i.second="<<i.second<<endl;
65     }*/
66     for(map<tree,int>::iterator it=p.begin();it!=p.end();it++)
67     {
68         cout<<"&dizhi="<<&it->first<<endl;
69         cout<<it->first.name<<" "<<it->first.id<<" i.second="<<it->second<<endl;
70     }
71     cout<<"可见,map左边为普通的实体对象时,修改对象上的数据,对已经存进map的数据没有修改\n";
72 }

推荐阅读