字符串反向迭代器的自适应性

时间:2018-05-21 20:28:34

标签: c++ string iterator language-lawyer

问题:

假设我有一个字符串,我想生成一个包含原始字符串且反向连接的新字符串。

以下是否可以保证有效?

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

我看到reserve应该恰当地设置capacity。但是,对反向迭代器应用append会导致那些迭代器失效吗?

其他背景:

我的C ++。11版(与C++.17 draft语言相同),§[string.capacity]

  

void reserve(size_type res_arg=0);

     
      
  1. 成员函数reserve()是一个指令,用于通知basic_string对象计划的更改   大小,以便它可以相应地管理存储分配。
  2.   
  3. 效果:reserve()之后,capacity()大于或等于保留的参数。 [注意:致电   reserve()参数小于res_arg的{​​{1}}实际上是非绑定收缩请求。   使用capacity()的呼叫实际上是一种非绑定的缩小到适合请求。 - 结束记录]
  4.   
  5. 抛出: length_error if res_arg <= size() 227
  6.               

    227) reserve()使用 allocator_traits :: allocate(),它可能抛出适当的异常。

虽然,§[string.append]说

  

res_arg > max_size()
      basic_string&

     
      
  1. 要求: append(const charT* s, size_type n);指向至少s n元素的数组。
  2.   
  3. 投掷: charT if length_error
  4.   
  5. 效果:该函数将size() + n > max_size()控制的字符串替换为长度为*this的字符串   其第一个size() + n元素是由size()控制的原始字符串的副本,其余为   元素是*this的初始n元素的副本。
  6.   
  7. 返回: s
  8.   

2 个答案:

答案 0 :(得分: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())在调用append的不同重载之前创建一个临时字符串,因此无论重新分配在另一个{ {1}}无关紧要。这意味着,即使没有先调用append,这也应该是安全的。

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

答案 1 :(得分:1)

修改

我不相信这个答案是正确的,请参阅评论。但为了保留有价值的评论,我将在那里留下答案。

最直接的追加看起来像是:

template<class T>
void string::append(T begin, T end) {
    reserve(size() + std::distance(end, begin));
    while (; begin != end; ++begin) {
       *this += *begin;
    }
}

由于在保留之后迭代器不应该无效,因此在整个函数期间,begin仍然对解除引用和递增有效。

在上面的示例中,reserve保证从我有权​​访问的最新草稿(http://eel.is/c++draft/string.capacity)中删除操作:

  

(24.3.2.4)void reserve(size_type res_arg);

     

#Effects:一个指令,用于通知basic_string计划的大小变化,以便相应地管理存储分配。   在reserve()之后,capacity()大于或等于参数   如果重新分配发生,则保留;并等于之前的值   容量()否则。此时重新分配会发生   如果当前容量小于reserve()的参数