2015-05-29 60 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

相关问题