标准是否保证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?
我问,因为我依靠它来避免堆碎片。
答案 0 :(得分:35)
[string.cons]/36
定义了根据移动分配将const char*
分配给std::string
的定义,
[string.cons]/32
basic_string& operator=(basic_string&& str) noexcept(/*...*/)
效果:Move分配作为序列容器,但迭代器,指针和引用可能无效。
这表明,委员会让执行程序在无效操作和更为保守的操作之间自由选择。为了使事情更加清晰:
[basic.string]/4
引用
basic_string
序列的元素的引用,指针和迭代器可能会由于以下basic_string对象的使用而失效:
- (4.1)作为任何标准库函数的参数,并以非常量
basic_string
的引用作为参数。- (4.2)调用非常量成员函数,但
operator[]
,at
,data
,front
,back
,begin
,rbegin
,end
和rend
。
我问,因为我依靠它来避免堆碎片。
std::string
将分配器作为模板参数。如果您真的担心可能出现的堆碎片,则可以编写自己的堆碎片,并通过一些启发式方法来制定适合您需求的分配策略。
在实践中,我所知道的大多数实现都不会在您遇到问题时重新分配内存。可以通过测试和/或检查您的实施文档以及最终的源代码来进行检查。
答案 1 :(得分:13)
CPP reference指出分配给指向字符的指针
将内容替换为s所指向的以空终止的字符串,就像* this = basic_string(s)一样,这涉及对Traits :: length(s)的调用。
这个“好像”实际上可以归结为一个右值赋值,因此很可能出现以下情况:
答案 2 :(得分:4)
如果从较小的字符串中重新分配了std :: string,是否可以保证std :: string不会自发地放弃分配的内存?
不管实际答案是什么(“不,不保证”),您都应遵循以下原则:如果不清楚是否必须这样做,则不要以为是
。在您的特定情况下-如果您想严格控制堆的行为,甚至可能根本不想使用std::string
(取决于情况)。而且您可能不想使用默认分配器(可能再次);并且您可能想memoize strings;等。您绝对应该做的是减少假设,进行可能的测量,并进行明确的设计以确保满足您的需求。
答案 3 :(得分:2)
如果您的字符串很短(最多15或22个字节,具体取决于编译器/标准库),并且您正在C ++ 11或更高版本的模式下使用相对较新的编译器,那么您很可能会受益于{ {3}}(SSO)。在这种情况下,字符串内容不会在堆上单独分配。
此链接还包含有关常见实现和分配策略的许多详细信息。
但是,示例中的两个字符串对于SSO来说都太长了。