STL Container和ATL智慧包裹類的衝突 (轉)
STL Container和ATL智慧包裹類的衝突:namespace prefix = o ns = "urn:schemas--com::office" />
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 filesmicrosoft vc98includelist(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 filesmicrosoft visual studiovc98includelist(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
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 s,無論何時,當你要把CComBSTR或者其他過載了operator&的類放入任何STL容器中時,請使用CAdapt。”
本文件所包含的資訊代表了在釋出之日,ZhengYun 對所討論問題的當前看法,Zhengyun 不保證所給資訊在釋出之日以後的準確性。
本文件僅供參考。對本文件中的資訊,Zhengyun 不做任何明示或默示的保證。
Written by zhengyun@tomosoft.com
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992783/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 採用JSI解決不同類庫間的衝突(轉)JS
- POP Animation 和 layoutSubviews 的衝突View
- 衝突處理的方法(轉載)
- Effective STL: Item 2: Beware the illusion of container-independent (轉)AI
- Activemq和Rabbitmq埠衝突MQ
- 簡談專案的衝突的管理(轉)
- 科研和工作並不衝突
- Elasticsearch和亞馬遜之間的衝突 - protocolElasticsearch亞馬遜Protocol
- 解決jquery和其他庫的衝突jQuery
- Laravel 6.0 的 predis 和 phpredis 衝突的原因LaravelRedisPHP
- svn檔案衝突,樹衝突詳解
- jQuery的$命名衝突jQuery
- jquery和dwr的util.js方法衝突jQueryJS
- wsl docker 和 ubuntu 衝突問題DockerUbuntu
- 教你玩轉Git-合併衝突Git
- 團隊間衝突管理策略(轉載)
- 為什麼docker 網段衝突會和宿主機衝突?原因分析和解決方案Docker
- commit 衝突MIT
- 雜湊衝突
- SVN衝突解決和注意事項
- 杜布林衝突的系統分析模型(轉載)模型
- Git 衝突了怎麼辦,如何高效快速的解決程式碼衝突?Git
- PCL(9)PLC庫和OpenCV庫中的FLANN衝突OpenCV
- 理解事件分發和衝突的實戰技巧事件
- exp工具的direct和query衝突以及程式補充
- cad快捷鍵和win10衝突怎麼辦_cad快捷鍵和win10衝突的解決方法Win10
- 如何避免javascript中的衝突JavaScript
- Flutter和iOS手勢衝突解決思路FlutteriOS
- 安裝vcenter server埠 80 和 IIS 衝突Server
- android NestedScrollView和ListView衝突問題AndroidView
- Linux中的衝突問題及其應對策略(轉)Linux
- Git 解決衝突Git
- git 解決衝突Git
- 查詢maven衝突Maven
- jQuery多庫衝突jQuery
- 一個類資料型別的STL例子 (轉)資料型別
- 資料轉換衝突及轉換過程中大物件的處理物件
- caffe框架和theano框架的所需cudnn的版本衝突問題框架DNN