请教Map
大家好,请看以下程序:
- C/C++ code
#include<map>#include<iostream>using namespace std;typedef map<int, char*> map_ch;void inert_element(map_ch &mymap){ char val[20] = "val"; mymap[0] = val;}int main(){ map_ch mymap; inert_element(mymap); cout << mymap[0] << endl; //请问此处输出的结果为什么有误? return 0;}但是这下这个程序为什么没有出错呢?
- C/C++ code
#include<map>#include<string>#include<iostream>using namespace std;typedef map<int, string> map_ch;void inert_element(map_ch &mymap){ string val = "val"; mymap[0] = val;}int main(){ map_ch mymap; inert_element(mymap); cout << mymap[0] << endl; return 0;}请问这两者有什么不同?谢谢!
[解决办法]
第一个用的是char*,在insert_element里面,map_ch[0]=一个函数栈里的字符串的指针,该函数返回后,这个指针指向的内容有可能改变了,所以会有误
第二个用的是string,在insert_element里面,map_ch[0]=val,这里用了复制构造函数,用val初始化了map_ch[0]里的string对象,所以在输出时不会有误。
[解决办法]
第一个程序错误是因为map的value指向了val,而val是一个栈变量。 inert_element结束,val生命周期终止,因此出错。第二个程序正确是因为map的value是string类型,它生成了val的拷贝。
[解决办法]
char val[20] = "val";
函数内的局部变量, 出了函数地址会变无效,出现非法访问非常正常
[解决办法]
map<int, char*>:inert_element(map_ch &mymap),形参mymap中的char*只是
main的副本,实参mymap的值并没有改变。
map<int, string>:inert_element(map_ch &mymap),形参mymap中的string是main的别名,通过别名可以改变实现没有mymap的值。
[解决办法]
[解决办法]
用char*的话,需要手动申请内存,之后才能赋值
[解决办法]
对于map map_name;直接用map_name[index],若index代表的键值不存在,系统会自动生成并且此时值为 "空 "(内置类型为0,类类型尤其默认构造函数生成)。
void inert_element(map_ch &mymap)
{
char val[20] = "val "; //val为局部变量
mymap[0] = val; //保存的指针值退出该函数后就成了野指针!!,因此外面输出会是乱码!
}
void inert_element(map_ch &mymap)
{
string val = "val "; //虽然val仍然是局部变量,但其未string类型
mymap[0] = val; //赋值时将相当于建立了val的副本!!
}
[解决办法]
[解决办法]
为什么这样写不出问题:
string val = "val";
mymap[0] = val;
因为mymap[0] 这条语句,隐藏了一些东西,首先查询key 0是否存在,如果不存在会自动insert一条 pari(0, val.c_str()),如果需要分配内存,则分配好内存。
[解决办法]
原因是这样的:
void inert_element(map_ch &mymap)
{
char val[20] = "val";
mymap[0] = val;
}
是分配20个char的数组,指针为val,数组存储的是“v,a,l,null”。比如val的值是0x00000001,则mymap[0]的值是0x00000001
这样,当函数inert_element结束后,mymap[0]的值还是0x00000001,但是指向该0x000000001的内存,有可能已经不是“v,a,l,null”了。因为这是栈中的数据。
而
void inert_element(map_ch &mymap)
{
string val = "val";
mymap[0] = val;
}
实际上是将 mymap[0]的值,赋值以字符串 "val",而不是字符串的指针。 mymap[0]其实是将原来的 string val = "val";进行拷贝构造得到的新的对象形成的字符串。
[解决办法]
map<int, char*> 保存char*
map<int, string> 保存string
错误在于保存的char*指向的内容无效了。