标准是否保证string::erase
和string::pop_back
DO NOT 重新分配内存?擦除一些元素后,string
可能会自动缩小吗?
我检查了标准,它说string::erase
和string::pop_back
要么抛出std::out_of_range
要么投掷任何东西。我是否可以将此作为这些方法 NOT 进行重新分配的保证?由于重新分配可能会抛出bad_alloc
。
答案 0 :(得分:3)
不,合理的实现可能不会重新分配,但标准并不能保证这些方法调用不会重新分配,标准会说明要求:
引用a的元素的引用,指针和迭代器
basic_string
序列可能会因以下用途而失效 那个basic_string对象:(4.1) 作为任何标准库函数的参数,将非const basic_string作为参数引用.227
(4.2) 调用非const成员函数,除了operator [],at,data,front,back,begin,rbegin,end和rend 。
两种提议的方法属于第2类,因此两者都可能会改变capacity()
,这隐含意味着重新分配。
pop_back
必须与erase
具有相同的效果,因为erase
被指定为:
效果:确定字符串的有效长度xlen 已删除
n
和size() - pos
中的较小者。 3然后,该函数将
*this
控制的字符串替换为长度为size() - xlen
的字符串,其第一个pos
元素是 由*this
控制的原始字符串的初始元素,和 其余元素是原始元素的副本 由位置*this
开始的pos + xlen
控制的字符串。
无法保证如何制作副本,因此可以进行额外分配或重新分配。
至于
我是否可以将此视为这些方法不做任何保证的保证 重新分配?由于重新分配可能会抛出
bad_alloc
。
该标准似乎没有明确提及由任何方法引起的bad_alloc
的可能性。即使绑定了reserve
,也没有提及它:
void reserve(size_type res_arg=0);
投掷:
length_error
res_arg > max_size()
因此我认为不能做出这样的假设。
答案 1 :(得分:2)
是的,您可以假设这些函数上的投掷:禁止重新分配(可能会抛出bad_alloc
)。
20.5.5.12异常处理的限制[res.on.exception.handling]
C ++标准库中定义的任何函数都可以报告 通过抛出中引用的类型的异常抛出失败: 段落,或从中命名的类型派生的类型: 将被基数的异常处理程序捕获的段落 类型。
...
C ++标准库中定义的没有的函数 抛出:段落,但确实有一个潜在抛出的异常规范可能抛出实现定义 例外。 186 实现应报告错误 抛出标准异常类的异常或派生 (21.6.3.1,21.8,22.2)。
请注意,规范没有明确说明标有" 的内容:没有。"不能扔任何东西。但在某些时候,常识必须接管。该标准也没有明确说明这些功能无法重新格式化您的磁盘。一般来说,标准规定了可以做的功能,并且不允许他们做任何其他。
函数抛出未在抛出:规范(或派生类型)中列出的异常的唯一方法是客户端以调用未定义行为的方式使用它。
答案 2 :(得分:1)
阅读documentation,我认为这取决于函数的签名。在basic_string& erase(size_type pos = 0, size_type n = npos);
的情况下,它被描述为前一个字符串的副本。在iterator erase(const_iterator first, const_iterator last);
的情况下,元素已删除。
实际上我对这种差异感到非常惊讶。我想你不能确定没有分配。
编辑请注意,在这个小例子中,我在每次检查时保留相同的地址:
#include <iostream>
int main()
{
std::string a;
for(std::size_t i = 0; i < 10000; ++i)
a += "Hello World ! My name is Bond... James Bond.";
std::cout << (long)&a[0] << std::endl;
a.erase(400000);
std::cout << (long)&(a[0]) << std::endl;
a.erase(10);
std::cout << (long)&(a[0]) << std::endl;
return 0;
}
答案 3 :(得分:1)
我认为这是有保证的,即使标准也没有明确说明。以下是关于reallocation对shrink_to_fit
的影响的说明:
备注:重新分配使引用序列中元素的所有引用,指针和迭代器以及过去的迭代器无效。如果没有重新分配,它们仍然有效。
如果重新分配发生,所有迭代器,指针,引用都将失效。但是erase
和pop_back
没有提到这一点;这意味着它们不会导致所有这些都失效,然后重新分配就不会发生。