模板类map插入一个自定义类对象遇到有关问题 求解
模板类map插入一个自定义类对象遇到问题 求解
项目中要用到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一个??
请各位大牛赐教~~谢谢~~!
------解决方案--------------------
------解决方案--------------------
问题一: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++;
------解决方案--------------------
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方式的拷贝构造函数以及赋值操作符一定会出问题。你必须显式提供自己的拷贝构造函数以及赋值操作符。
项目中要用到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一个??
请各位大牛赐教~~谢谢~~!
------解决方案--------------------
------解决方案--------------------
问题一: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++;
------解决方案--------------------
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方式的拷贝构造函数以及赋值操作符一定会出问题。你必须显式提供自己的拷贝构造函数以及赋值操作符。