13

在 C++ 标准库中,std::string有一个公共成员函数capacity(),它返回内部分配存储的大小,该值大于或等于字符串中的字符数(根据此处)。这个值可以用来做什么?它与自定义分配器有关吗?

4

7 回答 7

10

您更有可能使用reserve()成员函数,它将容量设置为至少提供的值。

capacity()成员函数本身可能用于避免分配内存。例如,您可以通过池回收使用过的字符串,并根据其容量将每个字符串放入不同大小的存储桶中。然后池的客户端可以请求已经具有一些最小容量的字符串。

于 2010-05-21T11:17:33.293 回答
6

string::capacity()函数返回在它必须重新分配内存之前可能包含的总字符数std::string,这是一个非常昂贵的操作。

Astd::vector以相同的方式工作,因此我建议您在std::vector 此处查找有关已分配内存和已初始化内存之间差异的详细说明。

更新

嗯,我可以看到我误读了这个问题,实际上我认为我自己从未在 std::string 或 std::vector 上使用过容量(),似乎很少有任何原因,因为无论如何你都必须调用 Reserve。

于 2010-05-21T11:17:14.887 回答
3

它为您提供了字符串可以包含的字符数,而无需重新分配。我想这在分配昂贵的情况下可能很重要,并且您想避免它,但我必须说这是我从未在实际代码中使用过的字符串成员函数。

于 2010-05-21T11:19:34.707 回答
2

如果您要向字符串中添加大量字符,它可以用于一些性能调整。在开始字符串操作之前,您可以检查容量,如果它太小,请在一个步骤中保留所需的长度(而不是让它连续多次重新分配更大的内存块,这将是一个性能猪)。

于 2010-05-21T11:17:17.990 回答
2

字符串有容量和大小。容量表示字符串在分配更多内存之前可以容纳多少个字符。大小表示它当前拥有多少个字符。reserve()可用于设置字符串的最小容量(它将为至少该数量的字符分配内存,但可以分配更多)。

如果您要增加字符串的大小,这主要是重要的。+=当您使用or连接到字符串时append(),给定字符串中的字符将被添加到当前字符串的末尾。如果将字符串增加到该大小不超过容量,那么它只会使用它拥有的容量。但是,如果新大小超过当前容量,则字符串必须在内部重新分配内存并将其内部复制到新内存中。如果您要经常这样做,它可能会变得昂贵(尽管它是在摊销的常数时间内完成的),因此在这种情况下,您可以使用reserve()预先分配足够的内存来减少重新分配的频率。

向量函数以基本相同的方式具有相同的功能。

就个人而言,虽然我不时处理capacity()和处理向量,但我从来没有看到有太多需要对字符串这样做 - 可能是因为我通常不会在我的代码中做足够的字符串连接以使其值得。reserve()在大多数情况下,一个特定的字符串可能会得到一些连接,但不足以担心它的容量。担心容量通常是您在尝试优化代码时所做的事情。

于 2010-05-21T11:22:05.090 回答
1

几乎没有任何相关用途。它类似于 std::vector::capacity。但是,字符串最常见的用途之一是赋值。当分配给 std::string 时,它的 .capacity 可能会改变。这意味着实现有权忽略旧容量并精确分配足够的内存。

于 2010-05-21T13:43:06.430 回答
1

它确实不是很有用,并且可能只是为了对称vector(假设两者将以相同的方式在内部运行)。

保证向量的容量会影响调整大小的行为。将向量调整为小于或等于容量的值不会导致重新分配,因此不会使引用向量中元素的迭代器或指针无效。这意味着您可以通过在向量上调用 reserve 来预先分配一些存储空间,然后(小心地)通过调整大小或向后推(等)向其中添加元素,在知道底层缓冲区不会移动的情况下是安全的。

但是,没有这样的保证string。似乎该容量仅用于提供信息的目的——尽管这有点牵强,因为看起来无论如何都没有任何有用的信息可以从中获取。(更糟糕的是,字符串字符的连续性也不能保证,因此您可以将字符串作为线性缓冲区获取的唯一方法是c_str()——这可能会导致重新分配。)

猜测一下,string大概最初打算作为 的某种特殊情况来实现vector,但随着时间的推移,两者逐渐分开......

于 2010-05-21T23:59:46.940 回答