如果双端队列不够大,为什么通过 std::copy 将 std::deque 对象附加到自身成功?
Why is appending std::deque object to itself through std::copy successful if the deque is not large enough?
书说的对,只是看错了一行
正如 明确指出的,以下问题取决于我的误读。
在阅读 Josuttis 的 C++ 标准库(第 2 版) 时,我不知何故确信第 457 页的 coll
被声明为 std::deque
(反之声明为std::list
!),所以才问这个问题
希望能为广大读者提供思想食粮
原始问题:
在 "The C++ Standard Library (2nd edition)" 的第 456 页,Josuttis 评论说,在您致电
之前
copy(coll.begin(), coll.end(), back_inserter(coll));
在 class std::vector
的 coll
上,您必须确保 coll
有足够的 space(在这种情况下,它有一个 capacity
至少是 size
的两倍),否则
the algorithm invalidates the passed source iterators while running.
相反,在第 458 页,他没有针对
的情况说任何类似的话
copy(coll.begin(), coll.end(), front_inserter(coll));
应用于 class std::deque
的 coll
,尽管在第 286 页,有关 std::deque
容器的指定如下:
[...] when elements are inserted at the front or the back. In this
case, references and pointers to elements stay valid, but iterators
don’t.
因此我怀疑。 (是的,我知道 std::deque
甚至不提供类似 reserve
的成员函数。)
只要我理解了this answer,我的理解是front_inserter(coll)
迭代器可以导致指针数组的重新分配(这是实现 std::deque
的合法方式),并且 不能 导致存储 coll
的实际元素的数组重新分配,从而留下 references/pointers 元素 有效,同时使 iterator
无效,其正确行为(我正在考虑如何实现 operator++
)依赖于数组指针和指向的数组。
如果这是真的,那么我猜对应于 copy
的参数 coll.begin()
的参数在分配给它的那一刻会失效导致指针数组的重新分配。
本书第455/456页介绍std::back_inserter
,第457/458页介绍std::front_insert
。每种情况都有一个简短的解释,包括适用容器的列表。每个部分都有一个代码片段作为示例,仅选择 一个 个适用容器来举例说明用法。
对于std::back_inserter
,由于选择了容器std::vector
,代码片段中的注释提到,为什么需要先在vector中预留足够的space。
对于 std::front_inserter
,作者选择了 std::list
,而不是 std::deque
。 std::list
不会在插入时使引用或迭代器失效,因此
copy(coll.begin(), coll.end(), front_inserter(coll));
可以,请参阅当前 C++ 草案的 [list.modifiers]/1。
因此,在这两种情况下,作者的代码都没有错误。我想他从来没有打算完全解释复制到容器本身的危险,而是简单地选择了这些案例,因为它允许他编写更短的完整用法示例。
我认为对于 coll
是 std::deque
的情况,这显然是未定义的行为。 std::front_inserter
通过调用 push_front
插入元素(参见 [front.insert.iter.ops]/2), which invalidates all iterators (see [deque.modifiers]/1):
同时std::copy
的行为是[alg.copy]/4:
Effects: Copies elements in the range [first, last) into the range
[result, result + N) starting from first and proceeding to last. For
each non-negative integer n <
N, performs *(result + n) = *(first + n).
第一次插入后,first
失效,会导致未定义的行为。
书说的对,只是看错了一行
正如
在阅读 Josuttis 的 C++ 标准库(第 2 版) 时,我不知何故确信第 457 页的 coll
被声明为 std::deque
(反之声明为std::list
!),所以才问这个问题
希望能为广大读者提供思想食粮
原始问题:
在 "The C++ Standard Library (2nd edition)" 的第 456 页,Josuttis 评论说,在您致电
之前copy(coll.begin(), coll.end(), back_inserter(coll));
在 class std::vector
的 coll
上,您必须确保 coll
有足够的 space(在这种情况下,它有一个 capacity
至少是 size
的两倍),否则
the algorithm invalidates the passed source iterators while running.
相反,在第 458 页,他没有针对
的情况说任何类似的话copy(coll.begin(), coll.end(), front_inserter(coll));
应用于 class std::deque
的 coll
,尽管在第 286 页,有关 std::deque
容器的指定如下:
[...] when elements are inserted at the front or the back. In this case, references and pointers to elements stay valid, but iterators don’t.
因此我怀疑。 (是的,我知道 std::deque
甚至不提供类似 reserve
的成员函数。)
只要我理解了this answer,我的理解是front_inserter(coll)
迭代器可以导致指针数组的重新分配(这是实现 std::deque
的合法方式),并且 不能 导致存储 coll
的实际元素的数组重新分配,从而留下 references/pointers 元素 有效,同时使 iterator
无效,其正确行为(我正在考虑如何实现 operator++
)依赖于数组指针和指向的数组。
如果这是真的,那么我猜对应于 copy
的参数 coll.begin()
的参数在分配给它的那一刻会失效导致指针数组的重新分配。
本书第455/456页介绍std::back_inserter
,第457/458页介绍std::front_insert
。每种情况都有一个简短的解释,包括适用容器的列表。每个部分都有一个代码片段作为示例,仅选择 一个 个适用容器来举例说明用法。
对于std::back_inserter
,由于选择了容器std::vector
,代码片段中的注释提到,为什么需要先在vector中预留足够的space。
对于 std::front_inserter
,作者选择了 std::list
,而不是 std::deque
。 std::list
不会在插入时使引用或迭代器失效,因此
copy(coll.begin(), coll.end(), front_inserter(coll));
可以,请参阅当前 C++ 草案的 [list.modifiers]/1。
因此,在这两种情况下,作者的代码都没有错误。我想他从来没有打算完全解释复制到容器本身的危险,而是简单地选择了这些案例,因为它允许他编写更短的完整用法示例。
我认为对于 coll
是 std::deque
的情况,这显然是未定义的行为。 std::front_inserter
通过调用 push_front
插入元素(参见 [front.insert.iter.ops]/2), which invalidates all iterators (see [deque.modifiers]/1):
同时std::copy
的行为是[alg.copy]/4:
Effects: Copies elements in the range [first, last) into the range [result, result + N) starting from first and proceeding to last. For each non-negative integer n < N, performs *(result + n) = *(first + n).
第一次插入后,first
失效,会导致未定义的行为。