将std :: string附加到自身是否安全?

Yir*_*kha 23 c++ stl

考虑这样的代码:

std::string str = "abcdef";
const size_t num = 50;

const size_t baselen = str.length();
while (str.length() < num)
    str.append(str, 0, baselen);
Run Code Online (Sandbox Code Playgroud)

std::basic_string<T>::append()像这样自己打电话是否安全?通过在复制操作之前放大,源内存是否无法生效?

我找不到该方法特有的标准中的任何内容.它说上面相当于str.append(str.data(), baselen),我认为可能不完全安全,除非内部有另外检测到这种情况append(const char*, size_t).

我检查了一些实现,他们似乎这样或那样安全,但我的问题是这种行为是否得到保证.例如" 将std :: vector附加到自身,未定义的行为? "说它不适合std::vector.

Rak*_*111 15

根据§21.4.6.2/§21.4.6.3:

函数[ basic_string& append(const charT* s, size_type n);]用长度为(+)+ n的字符串替换由*this控制的字符串,其第一个size()元素是由*this控制的原始字符串的副本,其余元素是初始n个元素的副本s.

注意:这适用于每一个append电话,因为每个append可以在以下方面来实现append(const charT*, size_type),由标准定义(§21.4.6.2/§21.4.6.3).

所以基本上,append使副本str(我们称之为副本strtemp),附加n的文字str2strtemp,然后替换strstrtemp.

对于该情况str2str,没有什么变化,因为当临时副本分配,而不是之前的字符串被放大.

即使标准中没有明确说明,也可以通过定义保证(如果实施完全符合标准)std::basic_string<T>::append.

因此,这不是未定义的行为.


Nic*_*las 6

这是复杂的.

有一点可以肯定.如果使用迭代器:

std::string str = "abcdef";
str.append(str.begin(), str.end());
Run Code Online (Sandbox Code Playgroud)

那么你保证安全.对真的.为什么?因为规范声明迭代器函数的行为等同于调用append(basic_string(first, last)).这显然会创建一个字符串的临时副本.因此,如果您需要在自身中插入一个字符串,那么您可以保证能够使用迭代器形式.

当然,实现不必实际复制它.但他们确实需要尊重标准的指定行为.只有当迭代器范围在其自身内部时,实现才可以选择复制,但实现仍然需要检查.

所有其他形式append都被定义为等同于调用append(const charT *s, size_t len).也就是说,你上面追加的电话等同于你做的append(str.data(), str.size()).那么标准对于s内部发生的事情的说法是什么*this

什么都没有.

唯一的要求s是:

s指向至少n元素的数组charT.

由于它没有明确禁止s指出*this,因此必须允许.如果迭代器版本允许自我赋值,那么它也会非常奇怪,但指针和大小版本却没有.