这种使用std :: string的方法是否安全?

时间:2015-05-29 08:23:51

标签: c++ string stl

我正在编写一个包含(拥有)std :: string的字符串类(Utf8String)(因为它非常方便)。

由于某种原因,我必须访问包装的std :: string的内部缓冲区才能直接写入它。我知道这很脏,而且反对封装原则和所有这些,但我必须这样做。

让以下Utf8String类成员:

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 个答案:

答案 0 :(得分: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中的内存。