std::string::resize() 对缓冲区一些用处

如果需要一个缓冲区来暂存字符串会先定义一个char*的数组来实现

存完后又给string赋值,感觉有点麻烦,寻思有什么方法可以更优雅点

比如如下代码

 1 void CVTString::StrToWStr(std::string& strString, std::wstring& wsString, unsigned int uCodePage)
 2 {
 3     int len = 0;
 4     wchar_t* buffer = nullptr;
 5 
 6     len = MultiByteToWideChar(uCodePage, NULL, strString.c_str(), static_cast<int>(strString.size()), NULL, NULL);
 7     buffer = new wchar_t[len + 1];
 8     MultiByteToWideChar(uCodePage, NULL, strString.c_str(), static_cast<int>(strString.size()), buffer, len);
 9     buffer[len] = L'\0';
10     wsString = buffer;
11 
12     delete[] buffer;
13 }

这个new可不可以去掉呢?这样的话buffer指针和delete也可以去掉了,性能应该有一丢丢提升

 

std::string有一个resize方法可以改变string分配的缓冲区大小

同时配合data方法来获取缓冲区的指针,这样可以实现一个char*数组效果的缓冲区。

 

但是注意的是string内部默认是分配了一个较小的缓冲区,如果resize的大小比较小

data方法的指针仍然不变,但是如果resize比较大,data返回的指针会变化

也就是会释放旧缓冲区,重新分配缓冲区。

这个大小的界限在vc上是16,也就是大于等于16的resize会重新分配缓冲区。

同时也就提醒我们,不要认为data和c_str返回的地址总是不变的。

如果是resize小于当前字符串长度,会直接截断字符串,也就是在目标长度的缓冲区补0,暂时没发现会进行重新分配。

 

resize还有一点,resize的长度默认是不包含字符串结束符号 \0 的,也就是resize(5),实际上会分配6的空间,最后一个字节补0

对于wstring则是补充\0\0

resize的第二个参数是填写补充的字符,resize(10,'x'),如果比原始字符串长,则会补充x字符,往小resize不会,而且依然会在最后补充结束符。

 

最终优化的代码(仅演示,一些错误处理没写)

 1 void CVTString::StrToWStr(std::string& strString, std::wstring& wsString, unsigned int uCodePage)
 2 {
 3     int charCount = MultiByteToWideChar
 4     (
 5         uCodePage, NULL, strString.c_str(), static_cast<int>(strString.size()), NULL, NULL
 6     );
 7 
 8     if (charCount == 0) return;
 9 
10     wsString.resize(charCount);
11     MultiByteToWideChar
12     (
13         uCodePage, NULL, strString.c_str(), static_cast<int>(strString.size()), const_cast<wchar_t*>(wsString.data()), charCount
14     );
15 }

2024年4月29日 :

不过以上代码还是有个性能问题的

resize是会分配空间+初始化每个元素,有些地方可能并不需要直接初始化对象(或者里面就需要写入数据,这时候初始化就成了不必要的操作),所以resize可能会造成一定的性能损失。

reserve 其实相当于预分配空间,防止因为push_back的时候不断重新分配空间造成性能下降(动态数组依据长度可能有1.5倍的扩容机制),当然这个只是单纯的改变capacity也就是对象分配的空间的大小,而不会改变对象内元素的数量

到C++23才有resize_and_overwrite来避免初始化操作。https://en.cppreference.com/w/cpp/string/basic_string/resize_and_overwrite

posted @ 2023-01-21 06:42  Dir-A  阅读(526)  评论(0编辑  收藏  举报