考虑这样的代码:
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的文字str2来strtemp,然后替换str用strtemp.
对于该情况str2是str,没有什么变化,因为当临时副本分配,而不是之前的字符串被放大.
即使标准中没有明确说明,也可以通过定义保证(如果实施完全符合标准)std::basic_string<T>::append.
因此,这不是未定义的行为.
这是复杂的.
有一点可以肯定.如果使用迭代器:
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,因此必须允许.如果迭代器版本允许自我赋值,那么它也会非常奇怪,但指针和大小版本却没有.
| 归档时间: |
|
| 查看次数: |
1912 次 |
| 最近记录: |