天天看點

C++ Types

LPCWSTR

LPCWSTR 是Unicode字元串指針,typedef __nullterminated CONST WCHAR *LPCWSTR, *PCWSTR; in WinNT.h

Convert example:

LPCWSTR text;

LPWSTR l=const_cast<LPWSTR>(text);

unsigned int maxResultSize=100;

const std::wstring ws=something;

LPWSTR lp;

wcsncpy_s(lp, maxResultSize, ws.c_str(), ws.size();

在頭檔案<atlconv.h>中定義了ATL提供的所有轉換宏,如:

A2CW (LPCSTR) -> (LPCWSTR)

A2W (LPCSTR) -> (LPWSTR)

W2CA (LPCWSTR) -> (LPCSTR)

W2A (LPCWSTR) -> (LPSTR)

所有的宏如下表所示:

A2BSTR

OLE2A

T2A

W2A

A2COLE

OLE2BSTR

T2BSTR

W2BSTR

A2CT

OLE2CA

T2CA

W2CA

A2CW

OLE2CT

T2COLE

W2COLE

A2OLE

OLE2CW

T2CW

W2CT

A2T

OLE2T

T2OLE

W2OLE

A2W

OLE2W

T2W

W2T

上表中的宏函數,非常的有規律,每個字母都有确切的含義如下:

2

to 的發音和 2 一樣,是以借用來表示“轉換為、轉換到”的含義。

A

ANSI 字元串,也就是 MBCS。

W、OLE

寬字元串,也就是 UNICODE。

T

中間類型T。如果定義了 _UNICODE,則T表示W;如果定義了 _MBCS,則T表示A

C

const 的縮寫

利用這些宏,可以快速的進行各種字元間的轉換。使用前必須包含頭檔案,并且申明USER_CONVERSION;使用 ATL 轉換宏,由于不用釋放臨時空間,是以使用起來非常友善。但是考慮到棧空間的尺寸(VC 預設2M),使用時要注意幾點:

1、隻适合于進行短字元串的轉換;

2、不要試圖在一個次數比較多的循環體内進行轉換;

3、不要試圖對字元型檔案内容進行轉換,因為檔案尺寸一般情況下是比較大的;

4、對情況 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();

2.HRESULT

HRESULT 是一種簡單的資料類型,通常被屬性和 ATL 用作傳回值。下表說明各種不同的值。頭檔案 winerror.h 中包含更多的值。

HRESULT 其實是一個雙位元組的值,其最高位(bit)如果是0表示成功,1表示錯誤。

HRESULT hr = 調用元件函數;

if( SUCCEEDED( hr ) ){...} // 如果成功

......

if( FAILED( hr ) ){...} // 如果失敗

3.什麼是BSTR

BSTR是“Basic STRing”的簡稱,微軟在COM/OLE中定義的标準字元串資料類型。

對于C++,Windows頭檔案wtypes.h中定義如下:

typedef wchar_t WCHAR;

typedef WCHAR OLECHAR;

typedef OLECHAR __RPC_FAR *BSTR;;

字元串相關類型的推薦選擇順序

優先級

類型

說明

最高

stl::string/wstring

●功能最完善,可移植性最好。

CString

●如果編碼規範限制使用STL的時候,推薦CString。 ●VC 6的版本很不完善。.Net有明顯改進,需要進一步研究

C/C++ basic type

(TCHAR* / char* /

LPTSTR / LPCTSTR / TCHAR[])

●在結構體中,優先使用指定最大長度的字元數組。 ●效率最好

CComBSTR/ _bstr_t

●在必須使用BSTR時的優先選擇。

●在ATL(COM component)工程或者工程中必須使用ATL中,優先選擇CComBSTR。一般Exe/dll如果_bstr_t能滿足要求,優先使用_bstr_t。

●對于VC6,使用_bstr_t一定要慎重,最好隻用作簡單臨時變量儲存調被調用函數的傳入參數。因為_bstrt_t不能支援一些關鍵性操作,比如Detach。

● 對于VC++ .Net推薦使用_bstr_t,它是C++擴充,不需要額外包含ATL的檔案。

最低

BSTR

● COM接口

4.CComBSTR

1. char

基本類型,1 byte 的串

2. wchar_t

unicode 串 2 byte

3. TCHAR

在16位程式下,表示為char,單位元組

在32位程式下,表示為unicode,兩位元組

4. 根據上面産生許多變種,一般都有相應的大定形式; 當在其中有P時,表示指針; 當在其中有C時,表示是常量

5. BSTR

定義的資料類型,一般COM調用的參數串

當define _UNICODE 它表示unicode串

否則 它表示ansi串

對了, 它前面有一個長度

6. CString _bstr_t CComBSTR 這三個是最好的東東

CString 封裝了char 與 w_char_t

_bstr_t 封裝了BSTR

CComBSTR 封裝了BSTR

CComBSTR、_bstr_t、BSTR、LPCTSTR、LPSTR、char *、CString

CComBSTR 是專門為COM的通用性而定制的一種格式

BSTR : unsigned short* 32位字元指針

LPCTSTR const char* 指向字元串常量的32位指針

char *; 字元串指針。

CString 字元串類。

LPTSTR const char* 指向可移植到Unicode和DBCS字元串常量的32位指針

LPSTR char * 可移植為的Unicode和DBCS字元串的32位指針。

4.std::wstring

const std::wstring obj;

const wchar_t *wt= obj.c_str();

Code : std::wstring ws;

ws=ws + L"" + BSTR

第0種方法:

std::wstring s2ws(const std::string& s)

{

std::wstring temp(s.length(),L‘ ‘);

std::copy(s.begin(), s.end(), temp.begin());

return temp;

}

std::string ws2s(const std::wstring& s)

std::string temp(s.length(), ‘ ‘);

第一種方法:調用WideCharToMultiByte()和MultiByteToWideChar(),

#include <string>

#include <windows.h>

using namespace std;

//Converting a WChar string to a Ansi string

std::string WChar2Ansi(LPCWSTR pwszSrc)

int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);

if (nLen<= 0) return std::string("");

char* pszDst = new char[nLen];

if (NULL == pszDst) return std::string("");

WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);

pszDst[nLen -1] = 0;

std::string strTemp(pszDst);

delete [] pszDst;

return strTemp;

string ws2s(wstring& inputws){ return WChar2Ansi(inputws.c_str()); }

//Converting a Ansi string to WChar string

std::wstring Ansi2WChar(LPCSTR pszSrc, int nLen)

int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);

if(nSize <= 0) return NULL;

WCHAR *pwszDst = new WCHAR[nSize+1];

if( NULL == pwszDst) return NULL;

MultiByteToWideChar(CP_ACP, 0,(LPCSTR)pszSrc, nLen, pwszDst, nSize);

pwszDst[nSize] = 0;

if( pwszDst[0] == 0xFEFF) // skip Oxfeff

for(int i = 0; i < nSize; i ++)

pwszDst[i] = pwszDst[i+1];

wstring wcharString(pwszDst);

delete pwszDst;

return wcharString;

std::wstring s2ws(const string& s){ return Ansi2WChar(s.c_str(),s.size());}

第二種方法:采用ATL封裝_bstr_t的過渡:(注,_bstr_是Microsoft Specific的,是以下面代碼可以在VS2005通過,無移植性);

#include <comutil.h>

#pragma comment(lib, "comsuppw.lib")

string ws2s(const wstring& ws);

wstring s2ws(const string& s);

string ws2s(const wstring& ws)

_bstr_t t = ws.c_str();

char* pchar = (char*)t;

string result = pchar;

return result;

wstring s2ws(const string& s)

_bstr_t t = s.c_str();

wchar_t* pwchar = (wchar_t*)t;

wstring result = pwchar;

5.std::pair

#include <iostream>

#include <utility>

03

04

05

06

int main () {

07

pair <string,double> product1 ("tomatoes",3.25);

08

pair <string,double> product2;

09

pair <string,double> product3;

10

11

product2.first = "lightbulbs"; // type of first is string

12

product2.second = 0.99; // type of second is double

13

14

product3 = make_pair ("shoes",20.0);

15

16

cout << "The price of " << product1.first << " is $" << product1.second << "/n";

17

cout << "The price of " << product2.first << " is $" << product2.second << "/n";

18

cout << "The price of " << product3.first << " is $" << product3.second << "/n";

19

return 0;

20

6.std::vector

簡單來講,std::vector 是一個動态數組,管理的是一塊線性的、可動态增長的記憶體。

如何加速 std::vector?

使用 vector::reserve

在大緻可預估 vector 大小時,在插入資料前,應該先調用 reserve(size) 進行記憶體的預配置設定(這裡 size是預估的vector元素個數)。

避免在vector開始(begin)插入/删除資料

也就是說,應該盡量用 vector::insert(end(), …) 或者 vector::push_back/pop_back添加/删除資料。而不要用 vector::insert(begin(), …)操作。vector 沒有提供 push_front操作,原因隻有一個:從 vector 開始處插入/删除資料是低效的做法。

如果你需要大量的在容器開始(begin)處 insert 資料,那麼可以選擇 std::deque(有 vector随機通路的優點,也有 list 高效插入的優點)或者 std::list.

std::vector 的缺陷

什麼時候不能用 std::vector ?

在容器需要容納海量資料,并且元素個數不可預知時,堅決不能用 std::vector.所有基于線性記憶體的資料結構(如std::vector,std::string)在海量資料時,遭遇性能瓶頸。

記憶體碎片

基于線性記憶體的資料結構(如 std::vector,std::string),還有一個典型的問題,就是容易産生記憶體碎片。在大量操作std::vector 或 std::string 後,記憶體碎片就會比較嚴重。

std::vector 與 allocator

我們知道,std::vector 的原型是:

template >

class vector;

那麼是否需要像我們針對Map/MultiMap、Set/MultiSet、List/Slist、HashMap/HashMultiMap、HashSet/HashMultiSet、Deque 做的那樣,将 AllocT 改用 GC Allocator呢?

答案是:不需要。GC Allocator 對于改善小記憶體配置設定是有益的。但是在動态的線性記憶體的資料結構無效。這樣的資料結構除了std::vector 外,典型的還有 std::string(std::basic_string)。

7._bstr_t

bstr_t類封裝BSTR有趣的地方就是它的封裝方式有點類似于智能指針,又有點像COM管理生存期的方式。_bstr_t将兩者結合起來并具體展現在構造函數、指派函數和析構函數中。

_variant_t和_bstr_t這兩個類分别封裝并管理VARIANT和BSTR這兩種資料類型,

VARIANT和BSTR這兩種類型是COM中使用的資料類型。

為了C++中的變量應用到ADO程式設計中,隻能進行資料類型的轉換。

通過_variant_t和_bstr_t這兩個類,就可以友善的把C++類型變量轉換成COM中的變量了

ADO是基于COM接口x實作的是以ta它的使用對于正在進行的 COMCOM程式設計的程式員而言更簡單

COMshi使用其特定的資料類型,_bstr_t是其中一種源類型

其他類型轉換成_bstr_t可以直接指派。

例子:

_bstr_t bstr("程式員");

const char *buf=bstrVar;

_bstr_t t("123");

t.GetBSTR();

_variant_t((LONG)value);

_variant_t v(something);

v.vt==VT_EMPTY || v.vt==VT_BSTR || v.vt==VT_NULL

8.boost::function

1. 介紹

Boost.Function 庫包含了一個類族的函數對象的包裝。它的概念很像廣義上的回調函數。其有着和函數指針相同的特性但是又包含了一個調用的接口。一個函數指針能夠在能以地方被調用或者作為一個回調函數。boost.function能夠代替函數指針并提供更大的靈活性。

2. 使用

Boost.Function 有兩種形式:首選形式和便攜式形式, 其文法如下:

首選形式

便攜式形式

boost::function<float(int x, int y)>f

boost::function2<float, int, int>f

但是便攜式形式不是所有的編譯器都支援的, 是以這裡我隻介紹首選形式。

2.1 普通函數

我們可以看下如下的例子:

1 void do_sum(int *values, int n)

2 {

3     int sum(0);

4     for (int i = 0; i < n; ++i)

5     {

6         sum += values[i];

7     }

8     cout << sum << endl;

9 };

10 int _tmain(int argc, _TCHAR* argv[])

11 {

12     boost::function<void(int *values, int n)> sum;

13     sum = &do_sum;

14     int a[] = {1,2,3,4,5};

15     sum(a, 5);

16     return 0;

17 }

sum 可以了解為一個廣義的函數對象了,其隻用就是儲存函數do_sum, 然後再調用之。

2.2 成員函數

在很多系統中, 對于類的成員函數的回調需要做特殊處理的。這個特殊的處理就是“參數綁定”。當然這個超出了我們讨論的範圍了。 boost::function對于成員函數的使用可以看下如下代碼:

1 class X{

2 public:

3     int foo(int a)

4     {

5         cout << a <<endl;

6         return a;

8 };

9 int _tmain(int argc, _TCHAR* argv[])

10 {

11     boost::function<int(X*, int)>f;

12     f = &X::foo;

13     X x;

14     f(&x, 5);

15     return 0;

16 }

我們發現, 對類的成員函數的對象化從文法是沒有多大的差別。

3. 一個典型的例子

上面的幾個例子沒有展現出boost::function的作用來, 這裡在寫一個例子。比如當程式執行到某一處的時候想綁定某一個函數, 但是不想立即執行, 我們就可以聲明一個函數對象,給此對象綁定相應的函數, 做一些其他事情,然後再來執行綁定的函數, 代碼如下:

1 void print(int a)

3     cout << a << endl;

4 }

5 typedef boost::function<void (int)> SuccessPrint;

6 int _tmain(int argc, _TCHAR* argv[])

7 {

8     vector<SuccessPrint> printList;

9     SuccessPrint printOne = boost::bind(print, _1);

10      printList.push_back(printOne);

11     SuccessPrint printTwo = boost::bind(print, _1);

12     printList.push_back(printTwo);

13     SuccessPrint printThree = boost::bind(print, _1);

14     printList.push_back(printTwo);

15     // do something else

16     for (int i = 0; i < printList.size(); ++i)

17         printList.at(i)(i);

18     return 0;

19 }

上述代碼中首先把聲明一個函數對象 typedef boost::function<void (int)> SuccessPrint, 然後把print綁定到斥對象中, 放入vector中, 到最後才來執行這print()函數。

Others:

boost::lexical_cast

boost::lexical_cast<std::wstring>(

boost::posix_time

boost::shared_ptr<DatabaseUtils>

boost::shared_ptr<PolicyPath::PoliciesVector>

boost::wformat

boost::bind(

boost::mem_fn(

boost::optional<>

boost::function<delegate * ...>

繼續閱讀