Visual Studio 中 std::string 的特定行为是什么?

6
我有一个需要读写大文件的项目。
我决定使用ifstream::read()一次性将这些文件读入内存中的std::string中。 (这似乎是在c++中最快的方法:http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.htmlhttp://insanecoding.blogspot.com/2011/11/reading-in-entire-file-at-once-in-c.html
当切换文件时,我需要“重置”用作先前内存缓冲区的std::string(即,擦除char[]缓冲区以释放内存)。
我尝试过:
std::string::clear()
std::string::assign("")
std::string::erase(0, std::string::npos)
std::string::resize(0)
std::string::reserve(0)

但是,在Visual Studio 2008下,这样不会释放std::string中使用的内存:其基础缓冲区不会被释放。

我发现唯一的方式是调用std::string::swap(std::string("")), 强制在实际std::string和参数中的空字符串之间更改内部缓冲区,从而删除它。

我觉得这个行为有点奇怪...

我只测试过Visual Studio 2008,不知道这是STL标准行为还是仅适用于MSVC。

你能给我一些线索吗?


5
交换(Swapping)是一种标准的让容器释放保留内存的方式。而使用std::string读取文件远非最优方式。 - user405725
1
@VladLazarenko:标准,可能是最快的。 - Nawaz
3
为什么你会期望有人去释放缓冲区?C++11 添加了显式的 shrink_to_fit() 方法来发起一个非绑定请求以进行内存释放。 - Kerrek SB
@Kerrek SB:谢谢,我还没有尝试过C++11,因为在我的公司里只允许使用Visual 2005/2008编译器 :/ - adrien.pain
1
交换是在C++98/C++03中缩小容量的惯用方式。在C++11中,您有一种方法shrink_to_fit,根据C++11 §21.4.4/14,“它是将capacity()减少到size()的非约束性请求。[注意:该请求是非约束性的,以允许实现特定的优化。—end note]”。祝好运! - Cheers and hth. - Alf
显示剩余2条评论
1个回答

4
正如Vlad和Alf所评论的那样,std :: string() .swap(the_string)是释放the_string容量的C ++ 98方式,而the_string.shrink_to_fit()是C ++ 11的方式。
至于为什么clear()erase()resize()等不会释放容量,这是一种优化,可以减少在多次使用字符串时进行分配。如果clear()释放了字符串的容量,则通常必须在下一次迭代中重新分配类似数量的空间,这需要一些时间,实现可以通过保留容量来节省。虽然这种实现不被标准保证,但在实现中非常普遍。 reserve()的文档如下:
调用具有小于capacity()的res_arg参数的reserve()实际上是一个非绑定收缩请求。使用res_arg <= size()的调用实际上是一个非绑定收缩到适合请求。
这意味着实现更有可能在reserve()调用时释放容量。如果我理解正确,libc ++和libstdc ++在调用reserve(0)时释放空间,但VC ++的库可能会做出相反的选择。
编辑:正如penelope所说,std :: string在这里的行为往往与std :: vector的行为完全相同。

1
我只想补充一点...... string 在大多数情况下的行为类似于 vector......而如果你向 std::vector 添加数据,当其大小达到保留容量时,它的容量会增加一倍(而且在大小缩小时不需要操作)。这样,在向矢量后端插入元素的时间几乎恒定,同时仍然在内存方面更有效:随着时间的推移,内存预留(缓慢的操作)的频率指数级减少,同时向量的大小从来没有超过所需大小的两倍。 - penelope

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接