3

这本书是对的,我只是看错了一句话。

正如@uneven_mark 的回答清楚地指出的那样,以下问题取决于我的误读。

在阅读Josuttis的 C++ 标准库(第 2 版)时,我以某种方式确信coll在第 457 页被声明为 a std::deque(相反,它被声明为std::list!),因此我问了这个问题。

希望可以作为读者的深思。

原始问题:

在“C++ 标准库(第 2 版)”的第 456 页,Josuttis 指出,在您调用之前

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

在 a collof class上std::vector,您必须确保它coll有足够的空间(在这种情况下,它有capacity至少两倍的size),否则

该算法在运行时使传递的源迭代器无效。

相反,在第 458 页,他没有对

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

应用于 a collof class std::deque,即使在第 286 页,针对std::deque容器指定了以下内容:

[...] 当元素插入到前面或后面时。在这种情况下,对元素的引用和指针保持有效,但迭代器则不然。

因此我怀疑。(是的,我知道std::deque甚至不提供类似reserve的成员函数。)

只要我理解了这个答案,我的理解是front_inserter(coll)迭代器可以导致指针数组的重新分配(这是一种合法的实现方式std::deque),并且不能导致coll存储实际元素的数组的重新分配,因此使指向元素的引用/指针有效,同时使iterators 无效,其正确行为(我正在考虑如何operator++实现)依赖于指针数组和指向数组。

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

4

1 回答 1

1

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

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

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

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

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

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

我认为对于这种情况,这显然是未定义的行为coll。通过调用插入元素(参见[front.insert.iter.ops]/2),这会使所有迭代器无效(参见[deque.modifiers]/1):std::dequestd::front_inserterpush_front

同时std::copys 的行为是[alg.copy]/4

效果:将范围 [first, last) 中的元素复制到范围 [result, result + N) 中,从 first 开始,一直到最后。对于每个非负整数 n < N,执行 *(result + n) = *(first + n)。

第一次插入后,first无效并导致未定义的行为。

于 2019-08-26T09:06:57.817 回答