我可以让std::string使用更少的内存吗
Can I make std::string use less memory?
在开始之前,我需要说明我的应用程序使用了大量字符串,这些字符串平均来说非常小,并且在创建后不会更改。
在VisualStudio2010中,我注意到std::string的容量至少为30。即使我写std::string str = "test";
,str的容量也是30。函数str.shrink_to_fit()
对此没有任何作用,尽管std::vector存在一个同名函数,并且按预期工作,即降低容量,使容量==大小。
- 为什么
std::string::shrink_to_fit()
不能按预期工作 - 如何确保字符串分配的内存最少
- 您的
std::string
实现很可能使用某种形式的短字符串优化,从而使较小字符串的大小固定,而对shrink_to_fit
没有影响。注意,shrink_to_fit
对于实现是不绑定的,所以这实际上是一致的 - 您可以使用
vector<char>
来获得更精确的内存管理,但会丢失std::string
的一些附加功能。您也可以编写自己的string
包装器,该包装器在内部使用vector
std::string::shrink_to_fit()
什么都不做的一个原因是标准不要求它
备注: shrink_to_fit是将
capacity()
缩减为size()
的非绑定请求。[注意:该请求是不绑定的,以允许实现特定优化的自由度。--结束注释]
如果你想确保字符串收缩,那么你可以像一样使用swap()
技巧
std::string(string_to_shrink).swap(string_to_shrink)
这可能不起作用的另一个原因是std::string
的实现者被允许实现短字符串优化,因此您的实现中的最小大小总是30。
你能做些什么取决于使用模式:
如果你的字符串是一个大字符串的一部分,这是典型的解析,你可以使用
std::experimental::string_view
、GSLstring_span
、Google的StringPiece、LLVM的StringRef等类,它们本身不存储数据,只引用其他字符串的一段,同时提供类似于std::string
的接口。如果有相同字符串的多个副本(尤其是长字符串),则使用CoW(写时复制)字符串可能是有意义的,其中副本使用引用计数器机制共享相同的缓冲区,直到被修改为止。(但要注意缺点)
如果字符串很短(只有几个字符),那么编写自己的专用类可能是有意义的,这与Andrzej 的Handling short codes一致
无论你选择什么情况,重要的是建立良好的基准程序,以清楚地看到你得到了什么效果(如果有的话)。
Upd:在重读了问题的引言之后,我认为第三种方法对你来说是最好的。
如果您在应用程序中使用了很多小字符串,那么您可能需要查看fbstring(https://github.com/facebook/folly/blob/master/folly/docs/FBString.md)。
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 为什么这个 std::queue/指向结构的指针列表直到 List.Size() == 0 才释放内存?
- 使 std::vector 分配对齐内存的现代方法
- std::unordered_map析构函数不释放内存?
- std::p romise::set_value() 和 std::future::wait() 是否提供内存围栏?
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 在共享缓冲区内存中创建 ::std::string 对象
- 内存未释放 std::list<std::shared_ptr<std::string>> C++
- <char> 使用 Vulkan 映射内存时如何使用 std::vector 而不是 void**?
- 我可以将新的 std::tuple 放入内存映射区域,并在以后读回吗?
- 如何防止使用 std::shared_ptr 的代码中的内存泄漏
- C++ 中 std::vector 的内存问题
- std::set 是否将对象连续存储在内存中?
- 如何在窗口之间移动 std::unique_ptr 而不会冒内存泄漏的风险?
- 为什么"std::uninitialized_copy"通常取消对未初始化内存的迭代器的引用不是未定
- vector是否为std::移动的对象连续分配内存
- Valgrind 在 std::make_unique 中显示内存泄漏
- std::initializer_list 堆是否分配内存?
- windows中的IPC共享内存std::vector