字符串反向迭代器的持久性,可自我附加

jxh*_*jxh 4 c++ string iterator language-lawyer

问题:

假设我有一个字符串,并且我想生成一个具有原始字符串并且反向连接的新字符串.

以下保证是否有效?

auto pq = [](std::string &s){
    s.reserve(2*s.size());
    s.append(s.rbegin(), s.rend());
};
Run Code Online (Sandbox Code Playgroud)

我认为reserve应该capacity适当地设定.但是,应用append反向迭代器会导致那些迭代器失效吗?

附加背景:

我的C++.11版本(与C++.17草案的语言相同)在§[string.capacity]中说

void reserve(size_type res_arg=0);

  1. 成员函数reserve()是一个指令,它通知basic_string对象计划的大小更改,以便它可以相应地管理存储分配.
  2. 效果:之后reserve(),capacity()大于或等于储备的参数.[ 注意:reserve()使用res_arg小于的参数调用 capacity()实际上是非绑定收缩请求.调用res_arg <= size()实际上是一个非绑定的缩小到适合请求.- 结束说明 ]
  3. 抛出: length_error if res_arg > max_size().227

227)reserve()使用allocator_traits::allocate()可能会引发适当的例外.

而§[string.append]说

basic_string&
append(const charT* s, size_type n);

  1. 要求: s指向至少n元素的数组charT.
  2. 抛出: length_error如果size() + n > max_size().
  3. 效果:该函数用*this长度字符串替换受控制的字符串,size() + n 其长度为第一个size()元素是*this由其控制的原始字符串的副本,其余元素是其初始n元素的副本s.
  4. 返回: *this.

Dan*_*l H 6

这不是std::string::append你实际调用的超载.你打电话的是template<class InputIterator> basic_string& append(InputIterator first, InputIterator last);.在那里,标准说([string.append]/21)它相当于在追加之前构造一个新的字符串:

效果:相当于append(basic_­string(first, last, get_­allocator())).

注意,在这里,构造函数调用在调用不同的重载之前basic_­string(first, last, get_­allocator())创建一个临时字符串,因此无论在另一个重新分配中发生什么都是无关紧要的.这意味着,即使没有先呼叫,这应该是安全的.appendappendreserve

请注意,无法保证字符串以这种方式实现; 标准说"等同于",而不是"已实施为".实现可以执行任何具有相同结果的操作,但在这种情况下,"相同的结果"意味着它仍然需要使用从调用它的相同字符串派生的迭代器.