C++ 将std::string附加到自身是否安全?
考虑到这样的代码:C++ 将std::string附加到自身是否安全?,c++,stl,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); std::string str=“abcdef”; 常量大小\u t num=50; 常量大小=长度(); while(str.length()
std::string str = "abcdef";
const size_t num = 50;
const size_t baselen = str.length();
while (str.length() < num)
str.append(str, 0, baselen);
std::string str=“abcdef”;
常量大小\u t num=50;
常量大小=长度();
while(str.length()
像这样对自身调用std::basic\u string::append()
安全吗?源内存不能在复制操作之前通过放大而失效吗
我在标准中找不到与该方法相关的任何内容。它说上面的内容相当于str.append(str.data(),baselen)
,我认为这可能并不完全安全,除非在append(const char*,size\u t)
中再次检测到这种情况
我检查了一些实现,它们看起来是安全的,但我的问题是,这种行为是否有保证。例如,“根据§21.4.6.2/§21.4.6.3,表示它不是用于
std::vector
:
函数[basic_string&append(const charT*s,size_type n);
]将*this控制的字符串替换为长度为size()+n的字符串,其第一个size()元素是*this控制的原始字符串的副本,其余元素是*this的初始n个元素的副本
注:这适用于每个append
调用,因为每个append
都可以按照标准(§21.4.6.2/§21.4.6.3)定义的append(const charT*,size_type)
实现
所以基本上,append
复制str
(我们称之为副本strtemp
),将str2
的n
字符追加到strtemp
,然后用strtemp
替换str
对于str2
为str
的情况,没有任何变化,因为在分配临时副本时,而不是之前,字符串会放大
尽管标准中没有明确规定,但通过std::basic_string::append
的定义可以保证(如果实现与标准中的规定完全一致)
因此,这不是未定义的行为。这很复杂
有一件事是可以肯定的。如果使用迭代器:
std::string str = "abcdef";
str.append(str.begin(), str.end());
那你就保证安全了。是的,真的。为什么?因为规范规定迭代器函数的行为等同于调用append(基本字符串(第一个,最后一个))
。这显然会创建字符串的临时副本。因此,如果需要将字符串插入到自身中,则可以保证能够使用迭代器形式来完成
诚然,实现不必实际复制它。但他们确实需要尊重标准规定的行为。只有当迭代器范围在自身内部时,实现才能选择创建副本,但实现仍需要进行检查
所有其他形式的append
被定义为等同于调用append(const charT*s,size\t len)
。也就是说,上面对append的调用相当于执行append(str.data(),str.size())
。那么,如果s
位于*此
的内部,该标准会说明什么
什么都没有
s
的唯一要求是:
s
指向图表的至少n
元素的数组
由于它没有明确禁止s
指向*此
,因此必须允许。如果迭代器版本允许自赋值,但指针和大小版本不允许,这也会非常奇怪。应该是这样,但我找不到任何方法<代码>str+=str
是合法的,归结起来是同一件事,所以我想它是好的。@NathanOliver:事实上,不把它定为非法是有充分理由的。对于字符串,将相同的字符串附加到其自身或字符串的子集是合理的。使用向量
,可能性要小得多。@Nicolas我明白了。我只是没有找到标准来支持我的论点。看起来像是Rakete1111。我明白了,谢谢-我应该读一下append(const charT*,size\u type)
的定义。