std:删除元素后,字符串容量保持不变,所以它是否占用了一些内存

std::string capacity remains same after deleting elements, so is it holding up some memory?

本文关键字:是否 内存 元素 删除 字符串 容量 std      更新时间:2023-10-16

以下代码:

string a = "abc";
cout << a.capacity();
a.erase(a.begin() + 1, a.end());
cout << a.capacity();

输出:

33

即使我从字符串中删除了一些元素,容量也保持不变。所以我的问题是:

  1. 内存是否因容量而被占用?如果我没有明确reserve()'d怎么办?

  2. 如果我使用reserve(),但最终没有使用全部容量,我是在浪费内存吗?

  3. 如果需要,这个额外的内存(我没有使用)会被分配给其他东西吗?

编辑:假设我有

string a= "something";
a = "ab";

现在我知道a的字符不会超过两个。那么,调用reserve(2)以避免内存浪费是否明智呢?

我会先回答您的问题:

  1. 内存属于字符串,但未完全使用。如果你不预订,你就无法控制容量。你只知道它足够大。

  2. 正确。

  3. 正如1)中所说:不。它属于字符串。没有其他东西可以使用这个内存。不过,字符串本身可以将其用于其他字符。

有关更多详细信息,我建议使用string::reserve的文档。

最后一句话:如果你从不预订,一切都会很好——不过可能会不必要地慢。只有当您频繁地添加几个字符,并且字符串必须重新分配很多(很像向量)时,才会出现这种情况。储备基本上是为了绕过这种情况。


在附录中:调用reserve可以帮助节省内存。如果调用reserve(n),这将确保字符串的内部容量至少为n个字符。注意,reserve不需要将容量精确地设置为n,也不需要降低小型n的容量(参见reserve文档)。

回到你的例子:如果你打电话给reserve,它永远不会造成任何伤害。总的来说,这是你能做的最好的事情。(如果您有C++11功能,我建议您使用shrink_to_fit)。

我用gcc/clang的(旧)版本进行了测试,在这种情况下,a的容量正好变为2。由于我不能100%确定添加的问题指的是什么,以下是我运行的内容:

auto a = string{"something"};
a = "ab";
cout << a << " " << a.capacity() << endl;
a.reserve(2);
cout << a << " " << a.capacity() << endl;

哪个生产:

ab 9
ab 2

1)是否有内存因容量而被占用?如果我没有呢显式保留()?

即使您没有调用reserve,std::string对象仍然可以为(甚至是默认构造的)std::string保留一些内存1。使用短字符串优化的std::string实现也是如此

2)如果我使用std::reserve(),并且最终没有使用整个capcity那我是在浪费记忆吗?

这取决于你所说的浪费内存是什么意思;CCD_ 22动态地调整其缓冲区的大小以适应字符串大小的变化。好吧,在Short String Optimizedstd::string实现的情况下,你对此无能为力。内存在字符串对象本身中。

3)我没有使用的额外内存会被分配给吗如果需要的话,还有别的吗?

否。std::string对象管理它分配的内存,它可以完全或部分放弃2,也可以不放弃,直到它被销毁。参见David Schwartz的评论

EDIT:假设我有

string a= "something";

现在我编辑字符串,知道a的长度不会超过两个字符。那么调用a.reserve(2)以使内存不浪费了?

如果以更改a.size()的方式修改a,例如调用resize方法或将其分配给长度为2的新字符串,则继续进行的reserve调用可能是有益的。

请注意,调用reserve不会减少字符串的内容。不允许std::string::reserve截断字符串。它只允许在未使用的内存上工作。如果使用小于字符串的size()new_capacity_intended调用std::string::reserve(new_capacity_intended),则可能发生的最佳情况与std::string::shrink_to_fit的效果相同。

减少字符串的内存(如果实现执行绑定shrink_to_fit请求)并将其缩减为前两个字符:

string a= "something";
//resize it first
a.resize(2);  //or by some assignment such as a = "so";
//then
a.reserve(2); // or better still a.shrink_to_fit();

1通过内存,我假设虚拟内存

2std::string::reservestd::string::shrink_to_fit可以放弃也可以不放弃字符串未使用的内存