我不明白为什么这段代码是准确的
vector<int> coll;
coll.reserve(2*coll.size());
copy (
coll.begin(), coll.end(), // zrodlo
back_inserter(coll) // przeznaczenie
);
Run Code Online (Sandbox Code Playgroud)
coll.end()代表矢量的结束.在我推回任何东西(如同back_insert_iterator)后,coll.end()返回的内容与之前的内容相同或不同之处?是否有多个终止迭代器?为什么end()可以用作容器的末尾,即使添加了新内容?
此外,您无法将代码应用于列表容器 - 它会卡住.这很重要,因为在向量的情况下,push_back使得迭代器在重新分配数据(何时size()==capacity()和push_back()被调用)后不可靠,而在列表的情况下则不是这样.为什么代码挂起列表?
编辑:(sscce)
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="")
{
typename T::const_iterator pos;
std::cout << optcstr;
for (pos=coll.begin(); pos!=coll.end(); ++pos) {
std::cout << *pos << ' ';
}
std::cout << std::endl;
}
int main(){
list<int> coll;
list<int>::iterator end = coll.end();
copy (
coll.begin(), coll.end(), // zrodlo
back_inserter(coll) // przeznaczenie
);
cout << *end << endl;
PRINT_ELEMENTS(coll);
}
Run Code Online (Sandbox Code Playgroud)
coll.end()在复制和后退插入开始之前被调用,所以基本上代码是相同的
coll.reserve(2*coll.size());
auto oldEnd = coll.end();
copy (coll.begin(), oldEnd, back_inserter(coll) );
Run Code Online (Sandbox Code Playgroud)
意思是,copy不会重新评估coll.end(),所以它不会注意/打扰它插入到同一个向量中,并且曾经是向量的结尾不是第一次插入后的结束.
相同的算法不会为列表编译,因为std::list没有reserve方法.但是,没有reserve它应该适用于lists,因为std::list::push_back不会使迭代器无效.你是正确的,std::vector::push_back当重新分配发生时,迭代器无效,所以进行reserve调用非常重要,因为它确保不需要重新分配.
的begin()和end()指针/用于确定什么将被复制到被评估一次,当被调用的函数迭代器.所以基本上std::copy()会增加它最终会到达的光标迭代器end(),因为vector<T>::const_iterator它只是T*旧学校数组上的一个奇特的指针.
正如您正确提到的,如果a push_back进行vector重新分配并将数据移动到内存中的其他位置,则复制的下一个元素将具有错误的源地址,这很可能最终会出现段故障.
对于列表,它永远不会终止,因为它end()是一个标记/保护指针,并且只能end()通过在列表的最后一个元素上递增迭代器来达到.所以end()它本身的地址永远不会改变,但是因为你不断在列表的末尾添加一个元素,你将永远不会到达最后一个元素,所以std::copy()永远不会获得指针end().有点像狗追逐它的尾巴.
通过插图和图表更容易理解,在双向链表和前哨节点上进行读取,这一切都有意义.
| 归档时间: |
|
| 查看次数: |
2029 次 |
| 最近记录: |