STL Container和ATL智能包裹类的冲突
来源:互联网 发布:手机有偿聊天软件 编辑:程序博客网 时间:2024/04/24 20:43
STL Container和ATL智能包裹类的冲突
Article last modified on 2002-8-7
----------------------------------------------------------------
The information in this article applies to:
- C/C++
- Microsoft Visual C++ 6.0(SP5)
----------------------------------------------------------------
现象:编译错误
如果你在程序中这么声明:
std::list< CComBSTR > list;
那么MSVC6.0(SP5)就会产生一个编译错误:
f:/program files/microsoft visual studio/vc98/include/list(238) : error C2664: 'destroy' : cannot convert parameter 1 from 'unsigned short ** ' to 'class ATL::CComBSTR *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
f:/program files/microsoft visual studio/vc98/include/list(235) : while compiling class-template member function 'class std::list
错误定位于List头文件的238行:
iterator erase(iterator _P)
{_Nodeptr _S = (_P++)._Mynode();
_Acc::_Next(_Acc::_Prev(_S)) = _Acc::_Next(_S);
_Acc::_Prev(_Acc::_Next(_S)) = _Acc::_Prev(_S);
allocator.destroy(&_Acc::_Value(_S));
_Freenode(_S);
--_Size;
return (_P); }
原因:重载operator&的行为破坏了CopyConstructible
按照C++标准,可以存储在任何容器中的对象都必须有CopyConstructible。
CopyConstructible的一个要求就是,假设t是存储在容器中的一个类型为T的对象,那么&t就返回T*,也就是t的地址。
而ATL的智能包裹类,如CComBSTr、CCOMPtr等,却都重载了操作符&,CComBSTR类的&操作符返回CComBSTR::m_str,这是一个BSTR类型。这样就破坏了CopyConstructible的要求。
说到这里,我们就不难理解为什么“error C2664: 'destroy' : cannot convert parameter 1 from 'unsigned short ** ' to 'class ATL::CComBSTR *'”了。
这种重载了&操作符的行为,在与STL联合使用时,会导致各种各样的问题(从内存泄漏到随机崩溃)。
这些危险对象包括有:
CComPtr
CComQIPtr
CComBSTR
_com_ptr_t
千万不要把它们放入任何STL容器中。当然也要留意其他重载了operator&的类。
解决办法:使用CAdapt模板类
ATL为我们提供了解决办法:CAdapt模板类。
这个模板重载了&操作符,不再让它返回对象的地址:
// AtlBase.h Line 864
template
class CAdapt
{
public:
。。。
operator T&()
{
return m_T;
}
operator const T&() const
{
return m_T;
}
T m_T;
};
CAdapt模板的历史意义就在于此。
这样我们就可以放心大胆地声明道:
std::vector< CAdapt > vect;
typedef vector< CAdapt< CComPtr< IWhatever > > > TWhateverVector;
不再会有麻烦。
总结:
下面的声明都不会有编译错误:
std::vector
std::vector< CComPtr
只有当容器是std::list时,才会发生编译错误。
而且,实际上使用下面的代码似乎也没有出现问题,比如内存泄漏等:
std::vector
vec.push_back(CComBSTR("string"));
对于这种情况,Igor Tandetnik是这么说的:
“有时候,你在STL Container中没有用CAdapt,看上去平安无事。但是,这样的话,你的代码就和STL厂商的具体实现密切相关了。从而当你调用以前从没有用过的容器的某一个方法时,可能会发生一些未定义的事情。所以,Just to be on the safe side,无论何时,当你要把CComBSTR或者其他重载了operator&的类放入任何STL容器中时,请使用CAdapt。”
本文档所包含的信息代表了在发布之日,ZhengYun 对所讨论问题的当前看法,Zhengyun 不保证所给信息在发布之日以后的准确性。
本文档仅供参考。对本文档中的信息,Zhengyun 不做任何明示或默示的保证。
Written by zhengyun@tomosoft.com
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=12686
- STL Container和ATL智能包裹类的冲突
- STL Container和ATL智能包裹类的冲突
- STL Container和ATL智能包裹类的冲突
- STL Container和ATL智能包裹类的冲突
- STL Container和ATL智能包裹类的冲突
- STL 容器和ATL智能包裹类的冲突
- ATL智能指针类
- wtl和atl的CString冲突时怎么办
- ATL 提供了2个智能指针的模板包装类CComPtr 和 CComQIPtr
- STL,ATL,WTL之间的联系和区别
- STL,ATL,WTL之间的联系和区别
- 【C/C++】STL,ATL,WTL之间的联系和区别
- STL,ATL,WTL之间的联系和区别
- STL,ATL,WTL之间的联系和区别
- STL,ATL,WTL之间的联系和区别
- STL,ATL,WTL之间的联系和区别
- STL,ATL,WTL之间的联系和区别
- STL,ATL,WTL之间的联系和区别
- 修复FrontPage服务器扩展对IIS的意外影响
- 【邦客】创业的那些事儿[一]
- 数位之墙的主题式汇整和机器自动聚合
- 监听以太网(三) Packet32数据结构说明
- 有些像穴道被打通之前的周星驰
- STL Container和ATL智能包裹类的冲突
- STL(shipped with VC6) Questions & Answers(四)
- 深入理解IIS运行时的身份
- 成于自信,毁于自卑
- 监听以太网(四) Packet32函数SDK
- [收藏]何谓聪明?
- 监听以太网(二) 关于Packet32 续
- COM+对象池组件崩溃调试手记
- 1+7=?我看看你是不是机器人