2015-05-29 68 views
1

我正在寫一個字符串類(Utf8String)包裝(有)一個std ::字符串(因爲它很方便)。這種方式使用std :: string安全嗎?

出於某種原因,我必須訪問包裝的std :: string的內部緩衝區才能直接寫入它。我知道這是骯髒的,反對封裝原則和所有這些,但我必須這樣做。

讓下面的UTF8字符串類成員:

std::basic_string<char> m_sBuf; 

inline char * Reserve(uint32_t nNewByteCap) 
{ 
    m_sBuf.reserve(nNewByteCap); 
    return const_cast< char * >(m_sBuf.c_str()); 
} 

inline void Resize(uint32_t nNewByteCount) 
{ 
    // Some stuff ... 
    m_sBuf.resize(nNewByteCount, ' '); 
} 

爲了做這樣的事情:

Utf8String sMessage; 
char * sBuffer = sMessage.Reserve(1024); 
uint32_t nRealLen = some_c_function_write_to_buffer(sBuffer, sMessage.Capacity()); 
sMessage.Resize(nRealLen); 

我不能肯定STL的內部工作原理。據我所知,它接受在std :: string中間丟失空字符,因此在字符串實際結束之前放置一個空字符應該不成問題。

由於STL的實現在不同的平臺上可能會有所不同,我的測試並不意味着它也可以在其他平臺上運行。

你看到這段代碼中可以破壞我使用的std :: string對象的東西嗎?謝謝你的幫助。

PS:我不能使用C++ 11。

+1

您對「reserve」和「resize」的使用沒有任何規定是合法的。無論容量如何,寫在字符串的* size *之外的行爲都有未定義的行爲。 –

+0

你是否聲明'返回m_sBuf.c_str();'在函數返回'char *'even * compiles *? – WhozCraig

+0

@KerrekSB我知道這不是使用std :: string的正確方法,這就是爲什麼我問,因爲我懷疑會有問題。如果我使用的是調整大小而不是保留? WhozCraig我爲這個問題寫了這段代碼,我只是忘了const_cast <>,但那不是重點。 – Virus721

回答

2

http://en.cppreference.com/w/cpp/string/basic_string/c_str

寫入()通過c_str訪問的字符數組是未定義的行爲。 你不應該那樣做。

更安全的代碼:

Utf8String sMessage; 
std::array<char, 1024> buffer; 
uint32_t nRealLen = some_c_function_write_to_buffer(buffer.data(), buffer.size()); 
sMessage.Assign(sBuffer.begin(), sBuffer.end()); 

最後一行假設你有你的字符串類:

template<typename InIt> 
void Assign(InIt begin, InIt end) { 
    m_sBuf.assign(begin, end); 
} 

(或同等學歷)。

這樣更好,因爲它不使用對c_str返回的數據的訪問,也不會嘗試手動管理std :: string中的內存。

+1

如果只需要'nRealLen'個數字,結果'sMessage'不會從'buffer'的所有1024個字符構建。 – WhozCraig

+0

也許吧。我把這個代碼留在了OP的問題中,並在我的回答中關注了字符串濫用。 – utnapistim

+0

感謝您的回答。我想通過使用new創建char緩衝區,並將此緩衝區分配給字符串(例如),但我的老闆不喜歡它,他想要類似於CString :: GetBuffer(),CString ::從MFC釋放(),這就是爲什麼我想出了問題中的設計。除了std :: array是C++,我不能使用。 – Virus721

相關問題