14 說說ATL常用包裝類的用法和坑

2021-08-06 03:23:03 字數 2940 閱讀 1342

atl提供了很多複雜資料型別的包裝類,使用這些包裝類可以大大減小開發工作量,但是他們使用起來也有許多坑,需要注意,本文就atl常用包裝類的用法和坑詳細說明,力圖說明產生這些坑的原因和使用注意事項。本文基於vs2008 atl,這一版修復了一些之前的bug。

先說通用的注意事項,所有的幫助類都類似智慧型指標特性(沒有引用),如下:

1.析構時釋放資源

2.賦值時,先釋放原來的內容,再分配建立新的內容

這要求使用時必須注意:

1.在coinitialize和couninitialize內使用介面指標

2.變數的生存週期,特別是棧上的變數

bstr使用需要注意兩點:

1.null是合法字串,bstr可能只包含null也可能中間包含null

2.bstr分配和釋放使用對應的sys...函式,否則很容易出現記憶體洩漏

常用構造如下:

ccombstr bstr1(olestr("test1"));

ccombstr bstr2(64, (lpcolestr)null); //支援null空字元

ccombstr bstr3(guid_test); //支援guid

支援長度為64內容為null的字串,支援guid直接轉成字串。

ccombstr bstr4;

bstr4 = olestr("test 4\0test 4");

bstr bt = ::sysallocstringlen(olestr("test 5\0test 6"), 13);

ccombstr bstr5;

bstr5.assignbstr(bt); //包含空字元時的賦值

使用&取ccombstr位址時,返回的是bstr字串,如果此時直接解引用操作返回的是bstr內容,=會導致直接覆蓋原有的bstr,導致記憶體洩露。

void getbstr1(bstr* pbstr)

void getbstr2(bstr* pbstr)

ccombstr bstr6 = olestr("test 7");

getbstr1(&bstr6);

getbstr2(&bstr6);

可以看到,getbstr1中直接對bstr賦值了,導致了記憶體洩漏,此時

可開啟atl的atl_ccombstr_address_of_assert巨集,該巨集判斷如果取&時,ccombstr不為空則報assert警告。也可以參考getbstr2中,可以使用函式sysreallocstring來處理這種情況。

variant使用時需要variantinit,然後指定型別和資料,使用完需要variantclear清除資源。ccomvariant為我們能封裝了整個過程,使用時直接賦值就行,模板例項化過程中會自動的找到對應型別,使用完自動釋放,如下:

ccomvariant v1 = 10;

ccomvariant v2 = 10.2;

ccomvariant v3 = olestr("test"); //預設轉成bstr

唯一需要注意的是,

ccomvariant不能使用未初始化的variant初始化(使用_atl_no_variant_throw巨集檢測),沒有初始化的ccomvariant也不能detach。

需要引入標頭檔案atlsafe.h。

ccomsafearray主要是為了簡化safearray的操作,常用操作如下:

void testsafearray()

; ccomsafearraysa4(bound4, 2); //2行3列double元素

/*****1維*****/

//新增

ccomsafearraysa5;

sa5.add(7);

int arr = ;

sa5.add(2, arr);

sa5.add(sa5);

//訪問

for (int i=0; i

1.ccomsafearray使用模板和巨集技術結合,將輸入型別int等等對映為實際com v_i4/v_i8。對於variant/bstr/idispatch和iunknown採用特化技術,這些型別get出來後會自動轉成ccomvariant/ccombstr/ccomptr,add/setat時通過指明bcopy引數來決定是使用拷貝還是託管現有。

2.ccomsafearray 建立後會呼叫lock,對應globallock函式,直到銷毀呼叫unlock,對應globalunlock,這樣做是假設使用者一直需要操作safearray資料。

3.attach和拷貝構造會校驗元素型別,最好不要直接通過getsafearrayptr操作指標。

原生com建立介面時需要使用cocreateinstance,傳入一大堆引數,呼叫麻煩。

ccomptr和ccomqiptr大大簡化了這一流程。通過內建擴充套件結合_uuidof,利用模板類是實現了加速編寫。後者相對前者,可以在賦值時動態查詢介面。

另外使用idispatch介面時,invoke時傳參非常麻煩,這些這兩個類中都做了封裝。

演示如下:

void testcomptr()

ccomqiptrspcat = spdog;

if (spcat)

}couninitialize();

}

可以看到這裡spcat賦值時,動態查詢了icat介面。

idispatch介面可直接呼叫invoke1/invoke2等引數。

需要注意的是:

1.賦值時,會自動addref

2.如演示程式,變數週期必須在com庫作用範圍內

3.使用->和.呼叫區別在於,前者呼叫內嵌指標,後者呼叫庫封裝的邏輯。一些函式比如release需要使用.訪問以呼叫對應的管理邏輯。

詳細內容可參考《atl深入解析》

常用的類 包裝類

基本資料型別所對應的包裝類 包裝類的預設值是null 對應關係 包裝就是將棧裡面的資料型別放堆裡面 byte byte short short int integer long long float float double double boolean boolean char character...

常用類的API Integer包裝類

bigdecimal可以對任意精度的資料進行運算,甚至可以運算超過long類的資料。建立bigdecimal物件,就是把資料封裝成物件。bigdecimal bd1 newbigdecimal 80.3 bigdecimal bd2 newbigdecimal 4.5 對兩個資料進行四則運算 加法 ...

14 類的常用魔術方法舉例

class fish object def init self,name self.name name print my name is s self.name f fish fish 9527 my name is fish 9527class fish object def new cls,ar...