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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- fcitx5 和 ibus的衝突
- Activemq和Rabbitmq埠衝突MQ
- 科研和工作並不衝突
- 教你玩轉Git-合併衝突Git
- Laravel 6.0 的 predis 和 phpredis 衝突的原因LaravelRedisPHP
- android NestedScrollView和ListView衝突問題AndroidView
- wsl docker 和 ubuntu 衝突問題DockerUbuntu
- maven 依賴衝突,忽略某個包中類的方法Maven
- cad快捷鍵和win10衝突怎麼辦_cad快捷鍵和win10衝突的解決方法Win10
- Elasticsearch和亞馬遜之間的衝突 - protocolElasticsearch亞馬遜Protocol
- 為什麼docker 網段衝突會和宿主機衝突?原因分析和解決方案Docker
- 解衝突用到的命令
- Android Webview和ScrollView衝突和WebView使用總結AndroidWebView
- 雜湊衝突
- VC++、MFC、COM和ATL的區別C++
- PCL(9)PLC庫和OpenCV庫中的FLANN衝突OpenCV
- 使用 etcd 和 grpc 遇到的版本衝突的那些事兒RPC
- Git 衝突了怎麼辦,如何高效快速的解決程式碼衝突?Git
- VMware無法啟動/VMware和wsl衝突問題/VMware與Hyper-V衝突問題
- 埠衝突,可愛的8080
- Flutter和iOS手勢衝突解決思路FlutteriOS
- lvm 名稱衝突LVM
- git 解決衝突Git
- Git 解決衝突Git
- STL中的迭代器分類
- H5-Jquery和Vue同時使用衝突H5jQueryVue
- git pull衝突的解決方案Git
- JAR衝突問題的解決JAR
- git如何進行程式碼的合併和衝突的解決Git行程
- InnoDB鎖衝突案例演示
- Manjaro更新出現衝突JAR
- 處理併發衝突
- [20200801]sql hint衝突.txtSQL
- 雜湊衝突詳解
- 程式衝突及其解決
- git pull 衝突解決Git
- hash衝突解決方法
- Git衝突解決技巧Git
- 用層級理解衝突