关于用vector管理CImage时遇到的坑
来源:互联网 发布:上杉升 知乎 编辑:程序博客网 时间:2024/06/15 17:11
假设有一个类A,里面有一个CImage。如果用vector储存,erase前面的元素后,后面的CImage就无法使用,会报ATLASSERT( hBitmap == m_hBitmap );
检查失败
struct A{ CImage img;};int _tmain(int argc, _TCHAR* argv[]){ vector<A> imgs(2); imgs[0].img.Create(1, 1, 32); imgs[1].img.Create(1, 1, 32); // 正常工作 imgs[0].img.GetDC(); imgs[0].img.ReleaseDC(); imgs[1].img.GetDC(); imgs[1].img.ReleaseDC(); imgs.erase(imgs.begin()); // 删除第一个img imgs[0].img.GetDC(); imgs[0].img.ReleaseDC(); // 出错,ATLASSERT( hBitmap == m_hBitmap );检查失败 return 0;}
GetDC和ReleaseDC是这样的
inline HDC CImage::GetDC() const throw(){ ATLASSUME( m_hBitmap != NULL ); m_nDCRefCount++; if( m_hDC == NULL ) { m_hDC = GetCDCCacheInstance()->GetDC(); m_hOldBitmap = HBITMAP( ::SelectObject( m_hDC, m_hBitmap ) ); } return( m_hDC );}inline void CImage::ReleaseDC() const throw(){ HBITMAP hBitmap; ATLASSUME( m_hDC != NULL ); m_nDCRefCount--; if( m_nDCRefCount == 0 ) { hBitmap = HBITMAP( ::SelectObject( m_hDC, m_hOldBitmap ) ); ATLASSERT( hBitmap == m_hBitmap ); GetCDCCacheInstance()->ReleaseDC( m_hDC ); m_hDC = NULL; }}
调试看了一下,ReleaseDC里的SelectObject返回值是NULL,更神奇的是上一句的GetDC里的SelectObject返回值也是NULL。看了一下SelectObject的文档,当调用失败时才返回NULL,而且一张BITMAP不能选入多个DC中。不过这里的BITMAP也没有选入多个DC啊,想了半天也没想出什么错误,直到我偶然调试到CImage的析构函数时发现,vector中的两个img的hBitmap居然是一样的
仔细想想,应该是vector删除前面元素时需要把后面的元素往前移动,然后不小心把后面的元素拷贝了一份,然后在后面元素的析构函数中把hBitmap释放了。查看erase的实现证实了我的想法
// TEMPLATE FUNCTION movetemplate<class _InIt, class _OutIt> inline _OutIt _Move(_InIt _First, _InIt _Last, _OutIt _Dest, _Nonscalar_ptr_iterator_tag) { // move [_First, _Last) to [_Dest, ...), arbitrary iterators for (; _First != _Last; ++_Dest, ++_First) *_Dest = _STD move(*_First); // 由于CImage没有实现移动的=操作符,这里调用了默认的拷贝的=操作符 return (_Dest); }
解决方法:
自己实现移动的=操作符
struct A{ A& operator= (A&& other) { img.Destroy(); img.Attach(other.img.Detach()); return *this; } CImage img;};
用指针管理CImage
int _tmain(int argc, _TCHAR* argv[]){ vector<unique_ptr<A> > imgs; imgs.push_back(make_unique<A>()); imgs.push_back(make_unique<A>()); imgs[0]->img.Create(1, 1, 32); imgs[1]->img.Create(1, 1, 32); // 正常工作 imgs.erase(imgs.begin()); imgs[0]->img.GetDC(); imgs[0]->img.ReleaseDC(); return 0;}
阅读全文
0 0
- 关于用vector管理CImage时遇到的坑
- 使用MFC CImage类绘制PNG图片时遇到的问题
- 使用MFC CImage类绘制PNG图片时遇到的问题
- 使用MFC CImage类绘制PNG图片时遇到的问题
- vector的内存管理
- vector的内存管理
- 用CImage加载内存里的Image
- 用CImage加载内存里的Image
- 用CImage加载内存里的Image
- 关于CImage和AlphaBlend的透明PNG图片显示问题
- vector使用遇到的问题
- ros&c++遇到的坑(vector 引起segmentation fault )
- 关于vector的使用
- 关于android studio中svn代码管理遇到的问题
- 关于IP遇到的坑
- 关于TabLayout遇到的坑
- 关于ajax遇到的坑
- 关于CImage加载透明图片
- spring学习总结
- caioj·1075: 动态规划入门(中链式2:能量项链)
- 博客前言
- Linux 的字符串截取
- java向上转型
- 关于用vector管理CImage时遇到的坑
- 《深度学习——Andrew Ng》第二课第二周编程作业
- 多说评论实时同步回数据库
- fragment 展示条目图片
- 第二周学习总结
- (转)终于把区块链的技术与应用讲清楚了ppt
- leetcode 11. Container With Most Water
- adb介绍以及常用命令
- Angular4.X 报错: Can't bind to 'ngModel' since it isn't a known property of 'input'