CComPtr对象作为参数进行 1.值传递 2.引用传递 3.做为返回值的注意事项
1.導致內存泄露的一種調用方式:
下面方法是錯誤的:
IA *pA=NULL;
p->QueryInterfaces(...,&pA);//從某個已有接口查詢獲取IA
CComPtr<IA> spA(pA)
QueryInterface方法會導致pA->AddRef被調用一次,CComPtr<IA>構造函數又會調用一次AddRef,而最后spA析構時只調用了一次Release,因此COM對象沒有被銷毀,內存泄露了。
?
?
正確做法如下:
??? IA *pA=NULL;
??? p->QueryInterfaces(...,&pA);
??? CComPtr<IA> spA;
? ? spA.Attach(pA);
或者
??? CComPtr<IA> spA(pA)
??? p->QueryInterfaces(...,&pA.p);
?
2.CComPtr內部對引用類型產生Assert原因
?
不能使用的operator&
?? //The assert on operator& usually indicates a bug.? If this is really
??? //what is needed, however, take the address of the p member explicitly.
??? T** operator&() throw()
??? {
??????? ATLASSERT(p==NULL);
??????? return &p;
??? }
??? 當你的CComPtr的p成員變量(集成而來的)不為NULL時,debug模式下會彈出錯誤對話框。看看上面的注釋,這個函數被設計用來防止對智能指針直接調用取地址操作符的。實在要用,請用這種方法:&sp.p。
?
3.CComPtr內部operator*
operator*
??? T& operator*() const
??? {
??????? ATLENSURE(p!=NULL);
??????? return *p;
??? }
??? 有了這個操作,我們就可以使得CComPtr擁有和普通指針同樣的行為,通過*p來獲得p所指對象的引用。
?
4.CComPtr內部operator T*
operator T*
??? operator T*() const throw()
??? {
??????? return p;
??? }
??? 這是個類型轉換操作。調用方法如下:
??? CComPtr<IUnknown> sp=...
??? IUnknown* p=(IUnknown*)sp;
?
5.CComPtr內部CopyTo
CopyTo
_Check_return_ HRESULT CopyTo(_Deref_out_opt_ T** ppT) throw()
??? {
??????? ATLASSERT(ppT != NULL);
??????? if (ppT == NULL)
??????????? return E_POINTER;
??????? *ppT = p;
??????? if (p)
??????????? p->AddRef();
??????? return S_OK;
??? }
??? 將自己的接口拷貝個參數指針,并調用AddRef。
6.CComPtr內部Attach和Detach方法
??? void Attach(_In_opt_ T* p2) throw()
??? {
??????? if (p)
??????????? p->Release();
??????? p = p2;
??? }
??? // Detach the interface (does not Release)
??? T* Detach() throw()
??? {
??????? T* pt = p;
??????? p = NULL;
??????? return pt;
??? }
??? Attach方法先釋放原先p所指接口,然后接受新接口,注意,不會導致AddRef調用。
??? Detach方法將p設置為NULLL,然后返回接口。如果外部調用需要保存返回的接口,否則就遺失了。
總結
以上是生活随笔為你收集整理的CComPtr对象作为参数进行 1.值传递 2.引用传递 3.做为返回值的注意事项的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解C++类的构造函数与析构函数
- 下一篇: WaitForSingleObject