2013-01-16 49 views
3

有誰根據this site知道爲什麼這個代碼是不正確的:爲什麼在使用可變參數函數時必須將CString強制轉換爲LPCSTR?

CString First("John"); 
CString Last("Doe"); 

CString Name; 

Name.Format("%s %s", First, Last); // Name may be garbage text 

Name.Format("%s %s", (LPCSTR)First, (LPCSTR)Last); // this is the correct way 

CString::Format微軟文檔中說:

...當你傳遞一個字符串作爲可選參數,你必須明確地將其作爲LPCTSTR投...

我總是使用「錯誤」的方式(沒有LPCSTR轉換),我從來沒有遇到過問題。

我失去了一些東西在這裏?

+0

關於此的有趣鏈接是[這裏](https://groups.google.com/forum/?fromgroups#!topic/microsoft.public.vc.mfc/Ao-A8D1-JT0)和[here](http ://stackoverflow.com/questions/922603/should-i-cast-a-cstring-passed-to-format-printf-and-varargs-in-general/924635#924635)。 –

回答

3

因爲沒有Format函數的內部完成投就像有是當你如果你寫printf("%d", a);沒有投做是爲了a因爲printf的假設%d已經告訴指定的參數printf()

沒有投做什麼數據類型a是。

爲了確保CString轉換爲LPCSTR即你需要轉換,這將調用操作員對返回LPCSTRCString參數%s。在CString的後續版本中,字符串被存儲起來,這樣當你沒有進行強制轉換時,它仍然會被打印爲LPCSTR,但要確保最好進行強制轉換。

或者以另一種方式:當一個可變參數函數經過的參數,它使用的格式說明知道的參數的大小,如果格式說明符不符合你的垃圾的論點。由於CString沒有格式說明符,因此需要將CString轉換爲LPCSTR。

順便說一句,你應該在C++

2

投射到LPCSTR使用static_cast<LPCSTR>(First), static_cast<LPCSTR>(Last)調用轉換運算符operator LPCSTR()(應該是operator const char *()

不調用LPCSTR意味着要傳遞的整個CString對象然後盲目地使用第一32或下面的結構作爲一個字符指針64個比特

總括:LPCSTR(str)被調用一個方法,以確保正確的行爲,而str是盲位操作

+0

這實際上是發生了什麼。如果你把一個CString對象作爲一個可變參數,編譯器實際上將CString對象的32個第一位壓入棧中。這在CString的情況下工作,因爲CString類的設計方式是任何CString對象的32位是指向實際字符串的指針。 –

+1

@MichaelWalz:你說的是,你對你的代碼是未定義的行爲感到滿意,並且取決於'CString'的實現細節,可能或不會改變,因爲在你的特定情況下它似乎工作。現在你的問題是*你爲什麼要施放?*並且答案很簡單,以避免未定義的行爲。 –

+0

@DavidRodríguez-dribeas,我沒有說我很高興,我只是說了究竟在做什麼。但是,如果CString類的佈局改變,那麼肯定使用一個強制轉換將節省你的一天。 –

1

我認爲(對不起,我沒有MFC現在可用於檢查)所需要只是爲了效率原因,投,以避免無用的臨時副本MFC必須做的時候如果參數類型未知(CString的是懶洋洋地複製在修改)。

它是CString的存儲器分配保留空間訣竅之前this爲比緩衝液(TCHAR *),如參考計數器其它一些必要的數據。

然後,當您通過值傳遞一個CString到一個可變參數函數時,它'看到'緩衝區(一個指針) 強制轉換'只提取'緩衝區,而不調用複製構造函數。

+1

實際上,當這種對象作爲可變參數傳遞時,並沒有創建臨時CString對象。在前面的答案中查看我的評論。 –

+0

@MichaelWalz:我在重新思考:應該有一個調用來拷貝構造函數(通過值傳遞的參數),但是由於'copy on modify',沒有緩衝區拷貝。 – CapelliC

+0

僅供參考:當您不使用演員時,不會調用複製構造函數。當你使用轉換時,調用操作符被調用,但不復制構造函數。請參閱以上Jeffery Thomas的回答。 –

1

因爲如果您使用子分類的CString參數它會中斷。

+0

使用微軟編譯器,即使你繼承了CString,它仍然繼續工作,但如果CString包含虛函數,那麼你會得到垃圾,因爲在這種情況下,前4個字節是nomore指向字符串的指針,但是指向虛函數表的指針。 –

+0

完全解釋它!不幸的是,我所有的dervied CString類都使用虛擬析構函數進行清理。我不確定我可以用非虛擬析構函數逃脫。我不使用CString * ptr = new CMyStringEx(),但另一個程序員可能有。 –

相關問題