首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

请问Map

2012-05-05 
请教Map大家好,请看以下程序:C/C++ code#includemap#includeiostreamusing namespace stdtypedef map

请教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*,在insert_element里面,map_ch[0]=一个函数栈里的字符串的指针,该函数返回后,这个指针指向的内容有可能改变了,所以会有误
第二个用的是string,在insert_element里面,map_ch[0]=val,这里用了复制构造函数,用val初始化了map_ch[0]里的string对象,所以在输出时不会有误。

[解决办法]
用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的副本!!
}

[解决办法]
探讨
也就是请问map元素通过string构造函数创建的对象是在堆上面创建的,还是在栈上面?有没有相关的资料可以参考呢?谢谢!

[解决办法]
为什么这样写不出问题:

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*指向的内容无效了。

热点排行