代码之家  ›  专栏  ›  技术社区  ›  jxh

用于自追加的字符串反向迭代器的耐久性

  •  4
  • jxh  · 技术社区  · 7 年前

    问题是:

    假设我有一个字符串,我想生成一个新的字符串,它将原始字符串及其反向连接起来。

    以下各项保证有效吗?

    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. 影响: 储备() , capacity() 大于或等于保留参数。[ ] 注: 打电话 储备() 用一个 res_arg 参数小于 容量() 实际上是一个非绑定的收缩请求。 与…通话 res_arg <= size() 实际上是一个非绑定的收缩以适应请求。 尾注 ]
    3. 抛出: 长度错误,如果 res_arg > max_size() . 二百二十七

    227) 储备() 使用 分配器_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() 元素是原始字符串的副本,由 *此 还有谁的剩余 元素是初始元素的副本 n 的元素 S
    4. 返回: *此
    2 回复  |  直到 7 年前
        1
  •  6
  •   Daniel H    7 年前

    这不是超负荷的 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 因此,无论在另一个系统中发生什么重新分配 追加 是无关的。也就是说,即使不打电话 reserve 首先,这应该是安全的。

    请注意,不能保证字符串是以这种方式实现的;该标准表示“等价于”,而不是“实现为”。实现可以做任何具有相同结果的事情,但在本例中,“相同的结果”意味着它仍然需要使用从调用它的相同字符串派生的迭代器。

        2
  •  1
  •   SergeyA    7 年前

    编辑

    我不相信这个答案是正确的,见评论。但是为了保留有价值的评论,我把答案留在那里。

    最简单的附加看起来是:

    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)空隙储备(尺寸_-type-res-arg);

    #影响:将计划的大小更改通知基本字符串的指令,以便相应地管理存储分配。 在reserve()之后,capacity()大于或等于 重新分配时的准备金;等于 否则为capacity()。只有当且仅当 如果当前容量小于reserve()的参数

    推荐文章