导航
  • 主页
  • VC综合技术
  • 互联网技术
  • MFC AppLauncher
  • .NET 技术
  • 界面
  • 进程
  • 算法
  • 硬件/系统
  • 数据库
  • VC++技术资源

模板类map插入一个自定义类对象遇到问题 求解

melody_zyp 2010-07-29 05:07:37
项目中要用到map,键为CString 值为自定义类 CFileAttribute ,在使用中遇到了以下问题,求解!!

问题一:
以下两种定义方式,在进行map.clear()的时候,内存释放上有啥不同?
typedef map<CString,CFileAttribute> MAPStr2FileAttr;
typedef map<CString,CFileAttribute *> MAPStr2FileAttr;

我是这样理解的
clear()相当于earse(m.begin(), m.end());

map<CString,CFileAttribute>:
这种方式下存入map的是副本,而不是要添加的对象本身。对象原件在副本拷贝存放结束后便可以结束生命。而在使用clear()的时候,对象副本会去走到析构函数,进行内部的内存释放。clear()后,对象拷贝被析构,剩下的只是raw memory,即没有被初始化的内存,它们将被归还到stl的内存分配器alloc里的,容器本身已经不再拥有这块内存了。

map<CString,CFileAttribute *>:
这时一般不能采用clear()函数,因为存入的是指针,这个指针指向一块区域(new出来的,eg:CFileAttribute *a = new CFileAttribute()),虽然在clear的时候这个指针指向的对象析构了,但是指针本身指向的new的空间还是没有被释放的,所以需要配合delete把这个指针指向的空间释放掉。

我的理解对吗????


问题二:
我采用map<CString,CFileAttribute> 这种方式,既map的value值为CFileAttribute对象,
但是在进行insert的时候程序却报错:

typedef map<CString,CFileAttribute> MAPStr2FileAttr;
MAPStr2FileAttr m_mapKeyVsFile;

szFilePath = "abc";
CFileAttribute FileAttr;
FileAttr.m_str = "nidfjasdkljfsdk";

m_mapKeyVsFile.insert(pair <CString,CFileAttribute> (szFilePath, FileAttr));

在执行insert的时候提示 _BLOCK_TYPE_IS_VALID 的错误,从网上查了下发现把CFileAttribute 的析构函数弄掉就OK了...
这是为什么呢??不是存入map的是原对象的副本吗,怎么还会涉及到析构函数??


问题三:
我在去掉析构函数后继续往下走
//srcfileAttribute.nIndex初始为0
CFileAttribute srcfileAttribute = m_mapKeyVsFile[“abc”];
srcfileAttribute.nIndex++;
但是再次
CFileAttribute srcfileAttribute = m_mapKeyVsFile[“abc”];
发现这个srcfileAttribute.nIndex还是0;并没有变成1,
这是为什么呢???
难道说我不能这样直接改map里面的value值吗?必须删除重新insert一个??



请各位大牛赐教~~谢谢~~!


...全文
284 点赞 收藏 5
写回复
5 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
wxh_cool 2012-05-23
有点说的不对,还需要重定向构造函数 CFileAttribute(CFileAttribute: &fileAttribute)
回复
hdq1115 2011-05-06
学习了,受教育了,今天在项目里面碰到类似的问题,非常感谢
回复
xxd_qd 2010-07-30
1、如果用容器存副本,则容器销毁的时候,副本也会自动被删除。如果用容器存指针,则容器销毁的时候,不会删除这些指针所指向的对象,因此必须先手工删除完毕之后,再销毁容器。

2、如果用容器存副本,其存入、取出的过程是通过拷贝构造函数和赋值操作符来进行的。如果你没有显式地提供这两者,则使用缺省的拷贝构造函数和赋值操作符,其实现方式为:内存复制。例如:假若你没有提供CFileAttribute::operator=,那么语句fileAttribute1 = fileAttribute2就相当于:memcpy(&fileAttribute1, &fileAttribute2, sizeof(CFileAttribute))。如果你的CFileAttribute仅包含简单变量,例如:
class CFileAttribute
{
int i;
double d;
};
那么memcpy没什么不妥。但假若你的CFileAttribute中包含(或者嵌套包含)指针,那么就可能有问题了,因为指针的复制并不等于内存块的复制,因此你必须显示地提供一个CFileAttribute::operator=,并且在其中把指针所对应的内存块也复制一遍,这才是真正的副本(此时这两个副本内的指针反而是不相等的,因为分别指向不同的内存块),其中任何一个副本的销毁(一般会在析构函数中把其指针所指向的内存块同时销毁)都不会影响到另一个副本的独立存在。
你的CFileAttribute::m_str显然是CString类型,而CString内部当然是一个指针,因此缺省的、memcpy方式的拷贝构造函数以及赋值操作符一定会出问题。你必须显式提供自己的拷贝构造函数以及赋值操作符。
回复
w382120035 2010-07-29
问题一:map<CString,CFileAttribute>里面的value是对象,clear的时候自动调用了每个value的析构函数;map<CString,CFileAttribute *>里面的value是指针,clear时只是把指针清除掉了,指针指向的内容依旧存在。一般要delete掉每个指针指向的空间,然后再clear。

问题二:等待高手。。。

问题三:srcfileAttribute = m_mapKeyVsFile[“abc”];此时srcfileAttrbute是通过map中值的拷贝构造函数构造的一个新的对象,这个副本的改变不影响map中的值,要改变map中的值可以直接m_mapKeyVsFile[“abc”].nIndex++;
回复
发动态
发帖子
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……