C++ 这种使用std::string的方法安全吗?

C++ 这种使用std::string的方法安全吗?,c++,string,stl,C++,String,Stl,我正在编写一个string类(Utf8String),它包装了一个std::string(因为它很方便) 出于某种原因,我必须访问包装好的std::string的内部缓冲区才能直接写入。我知道这是肮脏的,违反了封装原则,但我必须这么做 让以下Utf8String类成员: std::basic_string< char > m_sBuf; inline char * Reserve( uint32_t nNewByteCap ) { m_sBuf.reserve( nNewBy

我正在编写一个string类(Utf8String),它包装了一个std::string(因为它很方便)

出于某种原因,我必须访问包装好的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, ' ' );
}
我不确定STL内部是如何工作的。据我所知,它在STD::String的中间接受空字符,因此在字符串的实际结尾之前放置一个空字符不应该是问题。 由于STL的实现在不同的平台上可能不同,在我的平台上进行测试并不意味着它也可以在其他平台上工作

你在这段代码中看到了什么可以破坏我正在使用的std::string对象的东西吗?谢谢你的帮助

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

来自:

写入通过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());
Utf8String-sMessage;
std::数组缓冲区;
uint32\u t nrelen=一些函数写入缓冲区(buffer.data(),buffer.size());
sMessage.Assign(sBuffer.begin(),sBuffer.end());
最后一行假设字符串类中有:

template<typename InIt>
void Assign(InIt begin, InIt end) {
    m_sBuf.assign(begin, end);
}
模板
无效分配(初始开始,初始结束){
m_sBuf.分配(开始、结束);
}
(或同等标准)


这更好,因为它不使用对c_str返回的数据的访问,也不尝试手动管理std::string中的内存。

使用
reserve
resize
都是合法的。无论容量大小,超过字符串大小的写入都有未定义的行为。是否声明
返回m_sBuf.c_str()
在返回
char*
甚至编译的函数中?@KerrekSB我知道这不是使用std::string的正确方法,这就是为什么我要问,因为我怀疑会有问题。如果我使用resize而不是reserve呢?我为这个问题写了这段代码的人,我只是忘记了常量,但这不是真正的重点。如果生成的
sMessage
不是从
buffer
的所有1024个字符中生成的,而只需要
nrellen
个字符,那就更好了。可能吧。我将代码保留在OP的问题中,并在我的回答中重点讨论了字符串滥用。谢谢你的回答。我考虑过这样做,通过使用new创建一个char缓冲区,并将这个缓冲区分配给字符串(例如),但是我的老板不喜欢它,他想要类似于MFC中的CString::GetBuffer(),CString::Release(),这就是我提出这个问题的原因。除了STD::数组是C++,我不能使用。@ ViuS721是否他喜欢它“不”不使它正确。调用未定义的行为会导致灾难,我只祈祷无论你构建什么,他管理的都不是关键任务。把它做好。如果需要,重构您的代码并适当地管理
std::vector
。特别是
CString::GetBuffer
CString::Release
模型很糟糕-非常非常糟糕:它是一个依赖于正确编写客户端代码的接口(只是不要!),并要求您理解底层实现(不!). 当您没有正确使用这两个API时,应用程序会自动损坏。
template<typename InIt>
void Assign(InIt begin, InIt end) {
    m_sBuf.assign(begin, end);
}