c++ - 如果双端队列不够大,为什么通过 std::copy 成功将 std::deque 对象附加到自身?

标签 c++ copy language-lawyer deque inserter

书是对的,我只是看错了一行。

正如 answer by @uneven_mark 明确指出的,以下问题取决于我的误读。

在阅读 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));

std::vector 类的 coll 上,您必须确保 coll 有足够的空间(在这种情况下,它有容量至少是其大小的两倍),否则

the algorithm invalidates the passed source iterators while running.

相反,在第 458 页,他没有说任何类似的情况

copy(coll.begin(), coll.end(), front_inserter(coll));

应用于 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实际元素的数组的重新分配,从而留下引用/指向元素的指针有效,同时使迭代器无效,其正确行为(我正在考虑如何实现operator++)依赖于指针数组和指向数组。

如果这是真的,那么我猜对应于 copy 的参数 coll.begin() 的参数在分配给它的那一刻会失效导致指针数组的重新分配。

最佳答案

本书第455/456页介绍了std::back_inserter,第457/458页介绍了std::front_insert。每种情况都有一个简短的解释,包括适用容器的列表。每个部分都有一个代码片段作为示例,仅选择一个适用的容器来举例说明用法。

对于std::back_inserter,由于选择了容器std::vector,并且代码片段中的注释提到,为什么需要先在其中预留足够的空间 vector 。

对于 std::front_inserter,作者选择了 std::list,而不是 std::dequestd::list 不会在插入时使引用或迭代器无效,因此

copy(coll.begin(), coll.end(), front_inserter(coll));

很好,请参阅当前 C++ 草案的 [list.modifiers]/1

因此,在这两种情况下,作者的代码都没有错误。我想他从来没有打算完全解释复制到容器本身的危险,而是简单地选择了这些案例,因为它允许他编写更短的完整用法示例。

我认为对于 collstd::deque 的情况,这显然是未定义的行为。 std::front_inserter 通过调用 push_front(见 [front.insert.iter.ops]/2 )插入元素,这使所有迭代器无效(见 [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失效,会导致未定义的行为。

关于c++ - 如果双端队列不够大,为什么通过 std::copy 成功将 std::deque 对象附加到自身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57646965/

相关文章:

c++ - union 与位掩码和位移位

c++ - 如何将 Compiler 实例和 ASTConsumer 与 clang 3.6 一起使用

csv - Cassandra .csv导入错误:batch too large

c++ - 模板特化中的隐式转换

c++ - 在修改后的异常上使用 `throw;`

C++ 我是否错误地使用了 void 函数?

c++ - 为什么添加对右值引用的引用不是错误?

Python:深度复制ast节点树

java - 我想使用 poi 创建 word 或 excel 文件的副本

c++ - 在参数中移出的智能指针上调用方法是否安全?