当前位置: 代码迷 >> VC/MFC >> 在学习hash_地图为什么结构体可以直接使用不用指针
  详细解决方案

在学习hash_地图为什么结构体可以直接使用不用指针

热度:87   发布时间:2016-05-02 03:38:09.0
求助在学习hash_map为什么结构体可以直接使用不用指针
环境VS2010 2003系统 MFC框架以下是主要测试学习代码

有个几个问题不是很明白,NODE m_node 我定义个类里的变量

有点迷糊是初始化的时候, m_node 给里面每个变量赋值,之后再次添加又可以重复使用,我以前用容器的时候每次都是
PNODE m_node = new NODE 创建一个空间在单独复制 最后insert,而这次不用new也可以向里面插入数据,区别是new的删除的时候要用iterator遍历删除,这里有点迷糊map到底需不需要这样?


第二个迷糊的是 map这个 我的 更新、删除、查找 使用的对不对?(如果这样对那比之前其他的使用简单多了!)

第三个模糊的是insert 在关闭或者清理的时候要不要回收内存,看官方的文本mymap.erase (it); 好像这样就搞定了!
mymap.clear();  mymap.erase (it);看到2个都是清理这2个是不是都一样?不知道这样清理后内存还要做什么处理不?


stdafx.h 文件里

#include <hash_map>

typedef struct node
{
int uit;
CString name;
float  x;
}NODE , *PNODE;


*dlg.h 里定义
	hash_map<int, NODE > mymap;
hash_map<int, NODE >::iterator it;
NODE m_node;


主要代码
	
dlg.cpp 
   //这里是初始化时候添加到 mymap里的信息,我测试加了2个
m_node.name = "我是你的";
m_node.uit = 111;
m_node.x = 11.11;
mymap.insert(std::pair<int,NODE>(m_node.uit,m_node));

m_node.name = "11我是你的";
m_node.uit = 333;
m_node.x = 44.55;
mymap.insert(std::pair<int,NODE>(m_node.uit,m_node));

这里是按钮操作的
//这里是查找数据
it = mymap.find(111);
if (it != mymap.end())
TRACE("%s", it->second.name);


//这个是官方资料里删除
  it = mymap.find(111);
  if (it != mymap.end())
    mymap.erase (it);

这个是更新内容
it = mymap.find(111);
if (it != mymap.end())
it->second.name = ”我更新了 111这key“

------解决思路----------------------
m_node是建立在程序栈中的局部变量,它隶属于当前类的成员变量。如果使用New分配的内存它建立在堆中,它象公共变量一样,可以在任何类中使用,在线程间传递数据时常使用此方式,只要在某线程中将数据装入申请的内存,再将内存指针发给其它线程,就可以在其它线程中使用此数据块了。
成员变量在线程结束时自动被回收释放,而堆上申请的内存空间必须在程序中用语句自行释放,否则会造成内存泄漏。
------解决思路----------------------
你要搞清楚的是,STL容器“自己管理”容器里面的数据,具体来说吧
1、如果模板参数是个对象,譬如push_pack它会自己申请一个对象,把数据深拷贝进去,至于外面的数据生命周期怎么样就跟容器里面的没有关系了,因为它俩不是同一份数据,因此容器中的数据声明周期由容器本身的生命周期来决定,容器自己管理,我们不用管它

2、如果模板参数是个指针,譬如push_pack它会只申请一个指针大小的内存,即4字节,存入射进来的那个指针,而不是把指针所指向的内存给拷进来,话句话说,容器析构的时候析构的只是指针自身,并不会析构该指针指向的内存!因此,这种情况必须由程序员自己去管理指针内存数据,适时手动delete,否则就会造成内存泄露


------解决思路----------------------
不要以为我说的就是对的,实践才是真理,你最好去验证一下:

m_node.name = "我是你的";
m_node.uit = 111;
m_node.x = 11.11;
mymap.insert(std::pair<int,NODE>(m_node.uit,m_node));

m_node.name = "11我是你的";
m_node.uit = 333;
m_node.x = 44.55;
mymap.insert(std::pair<int,NODE>(m_node.uit,m_node));
//.......

在mymap.insert这两句的下一句各打个断点,F5启动调试,每次insert完之后你看看mymap容器里面的对象地址,以及对象中的各个成员地址,跟m_node的地址及它的相对应的成员地址比较一下,看看是否是一样的,如果地址是一样的,说明什么;不一样,又说明了什么?
------解决思路----------------------
我已经说的很清楚了啊
地址一样表示浅拷贝——只有一份内存
地址不一样表示深拷贝——有两份内存

这个需要你自己去亲自验证,方能理解的深刻些
------解决思路----------------------


内存地址啊,非内存内容!无论是深浅拷贝,内容肯定是一样的啊!

int a = 10;
&a表示变量a在内存中的地址(4字节内存首地址),即位置,这4字节的内存存的内容是10



------解决思路----------------------
理解讨论之前请先学会如何观察

计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!

单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

------解决思路----------------------
引用:
Quote: 引用:



内存地址啊,非内存内容!无论是深浅拷贝,内容肯定是一样的啊!

int a = 10;
&a表示变量a在内存中的地址(4字节内存首地址),即位置,这4字节的内存存的内容是10
我这个是怎么弄,之前那样操作有问题不

估计是我把你绕糊涂了,你又没怎么深刻体会我讲的精髓,所以我不多说了

你要多想,多思考,别老想着让别人手把手教你。自己领悟出来的东西,才是属于你自己的啊!你再仔细看看我3L讲的,多动脑多动手,再结合你提的那几个问题,应该不难理解吧....
  相关解决方案