std::string 保证不自发回馈内存?

Is std::string guaranteed not to give back memory spontaneously?

标准是否保证 std::string 如果从较小的字符串重新分配,则不会自发归还已分配的内存?

换句话说:

std::string str = "Some quite long string, which needs a lot of memory";
str = "";
str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation?

我问是因为我依赖它来避免堆碎片。

没有任何保证。

[string.cons]/36定义了将const char*分配给std::string的移动分配,其定义是:

[string.cons]/32

basic_string& operator=(basic_string&& str)  noexcept(/*...*/)

Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated.

这表明委员会让实施在无效操作和更保守的操作之间自由选择。为了让事情更清楚:

[basic.string]/4

References, pointers, and iterators referring to the elements of a basic_­string sequence may be invalidated by the following uses of that basic_­string object:

  • (4.1) as an argument to any standard library function taking a reference to non-const basic_­string as an argument.
  • (4.2) Calling non-const member functions, except operator[], at, data, front, back, begin, rbegin, end, and rend.

I ask because i'm depending on this to avoid heap fragmentation.

std::string 将分配器作为模板参数。如果您真的担心可能的堆碎片,您可以编写自己的代码,通过一些启发式方法可以有适合您需要的分配策略。

实际上,我所知道的大多数实现都不会在您提出问题的情况下重新分配内存。这可以通过测试 and/or 检查您的实施文档和最终源代码来检查。

CPP reference 表示对指向字符的指针的赋值

Replaces the contents with those of null-terminated character string pointed to by s as if by *this = basic_string(s), which involves a call to Traits::length(s).

这个"as if"实际上归结为一个右值赋值,所以下面的场景是很有可能的:

  1. 创建了一个新的临时字符串。
  2. 这个 字符串通过分配给右值引用窃取其内容。

如果您的字符串很短(最多 15 或 22 个字节,具体取决于 compiler/std 库)并且您使用的是相对较新的 C++11 或更高版本的编译器,那么您很可能受益于 Short String Optimization (SSO)。在这种情况下,字符串内容不会在堆上单独分配。

这个link还包含很多关于常见实现和分配策略的细节。

但是,您示例中的两个字符串对于 SSO 来说都太长了。

Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size?

不管实际答案是什么("No, no guarantee")——您应该遵循以下原则:如果情况并非如此,则不要假设是这样的

在您的特定情况下 - 如果您想要严格控制堆行为,您可能根本不想使用 std::strings(也许;这取决于)。而且您可能不想使用默认分配器(同样,也许);你可能想要 memoize strings;等。您绝对应该做的是少做假设,尽可能进行测量,并进行明确的设计以确保满足您的需求。