STL Container和ATL智能包裹类的冲突

载自:http://www.codesky.net/article/200504/63245.html

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<class ATL::CComBSTR,class std::allocator<class ATL::CComBSTR> >::iterator __thiscall std::list<class ATL::CComBSTR,class std::allocator<class ATL::CComBSTR> >::erase(class std::list<class ATL::CComBSTR,class std::allocator<class ATL::CComBSTR> >::iterator)'

错误定位于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 T>

class CAdapt

{

public:

    。。。

       operator T&()

       {

              return m_T;

       }

       operator const T&() const

       {

              return m_T;

       }

       T m_T;

};

CAdapt模板的历史意义就在于此。

这样我们就可以放心大胆地声明道:

std::vector< CAdapt <CComBSTR> > vect;
typedef vector< CAdapt< CComPtr< IWhatever > > > TWhateverVector;

不再会有麻烦。

总结:

下面的声明都不会有编译错误:

std::vector<CComBSTR > vecBSTR;

std::vector< CComPtr<IPDH> > vecPDH0;

只有当容器是std::list时,才会发生编译错误。

而且,实际上使用下面的代码似乎也没有出现问题,比如内存泄漏等:

std::vector<CComBSTR > vec;

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 不做任何明示或默示的保证。

STL Container和ATL智能包裹类的冲突的更多相关文章

  1. 智能指针类模板(上)——STL中的智能指针

    智能指针类模板智能指针本质上就是一个对象,它可以像原生指针那样来使用. 智能指针的意义-现代C++开发库中最重要的类模板之一-C++中自动内存管理的主要手段-能够在很大程度上避开内存相关的问题 1.内 ...

  2. C++中的智能指针类模板

    1,智能指针本质上是一个对象,这个对象可以像原生的指针一样使用,因为智能指 针相关的类通过重载的技术将指针相关的操作符都进行了重载,所以智能指针对象可以像原生指针一样操作,今天学习智能指针类模板,通过 ...

  3. c/c++ 模板与STL小例子系列<二> 模板类与友元函数

    c/c++ 模板与STL小例子系列 模板类与友元函数 比如某个类是个模板类D,有个需求是需要重载D的operator<<函数,这时就需要用到友元. 实现这样的友元需要3个必要步骤 1,在模 ...

  4. Android中View类OnClickListener和DialogInterface类OnClickListener冲突解决办法

    Android中View类OnClickListener和DialogInterface类OnClickListener冲突解决办法 如下面所示,同时导入这两个,会提示其中一个与另一个产生冲突. 1i ...

  5. Maven类包冲突终极解决方案

    本文转自:http://ian.wang/106.htm 举例A依赖于B及C,而B又依赖于X.Y,而C依赖于X.M,则A除引B及C的依赖包下,还会引入X,Y,M的依赖包(一般情况下了,Maven可通过 ...

  6. Maven类包冲突终极三大解决技巧 mvn dependency:tree

    Maven对于新手来说是<步步惊心>,因为它包罗万象,博大精深,因为当你初来乍到时,你就像一个进入森林的陌生访客一样迷茫. Maven对于老手来说是<真爱配方>,因为它无所不能 ...

  7. [转]Maven类包冲突终极三大解决技巧

    举例 A依赖于B及C,而B又依赖于X.Y,而C依赖于X.M,则A除引B及C的依赖包下,还会引入X,Y,M的依赖包(一般情况下了,Maven可通过<scope>等若干种方式控制传递依赖).这 ...

  8. 记一次多个Java Agent同时使用的类增强冲突问题及分析

    摘要:Java Agent技术常被用于加载class文件之前进行拦截并修改字节码,以实现对Java应用的无侵入式增强. 本文分享自华为云社区<记一次多个JavaAgent同时使用的类增强冲突问题 ...

  9. 问题解决——在STL的queue中使用自定义类

    本文原创,转载请保证文章的完整性,并显要的注明出处. 本文链接:http://blog.csdn.net/wlsgzl/article/details/38843513 平时很少用STL,就算用,也基 ...

随机推荐

  1. imindmap7_windows_7.0

    思维导图工具: imindmap7_windows_7.0 iMindMap7.0 和谐包V1.0 22:27:23

  2. 编写你自己的单点登录(SSO)服务

    王昱 yuwang881@gmail.com   博客地址http://yuwang881.blog.sohu.com 摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统其中.本文从 ...

  3. SGU 531. Bonnie and Clyde 线段树

    531. Bonnie and Clyde 题目连接: http://acm.sgu.ru/problem.php?contest=0&problem=531 Description Bonn ...

  4. Codeforces Good Bye 2015 D. New Year and Ancient Prophecy 后缀数组 树状数组 dp

    D. New Year and Ancient Prophecy 题目连接: http://www.codeforces.com/contest/611/problem/C Description L ...

  5. [Ember] Ember.js Templates

    In this lesson, we'll go over some of the basics of Ember.js templates and how they work with contro ...

  6. Linux VM子系统参数调整

    Timesten数据库下的Linux page子系统参数调整  如果Timesten(TT)采用了Durablecommits或是share memory segment被lock的话,那么linux ...

  7. Feister network

    在密码学中,Feister network(又叫Feister Function, 一下简称 F函数)是一种用在块加密上的对称结构,很多种块加密算法都是使用这种结构. 优点: 1.加解密的过程非常相似 ...

  8. java使用jsp servlet来防止csrf 攻击的实现方法

    背景: 1.csrf知识 CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或 ...

  9. 《嵌入式Linux基础教程学习笔记一》

    常用书目下载地址:http://www.cnblogs.com/pengdonglin137/p/3688029.html 第二章 1.进程上下文和中断上下文(Page20) 当应用程序执行系统调用, ...

  10. No Entertainment!

    今天决定去打印一个“No Entertainment”的横幅,贴在电脑的旁边.这其实是很久以前的事了,却搁浅到了现在.也正因为如此,今天想起来也觉得格外刻不容缓,内心好似义愤填膺,便写下这愤慨的独白. ...