C ++中`inserter`的机制是什么?

时间:2017-04-12 14:04:31

标签: c++ c++11

我尝试了代码,inserterback_inserter使lst3相同,但我认为inserter应生成{4,3,2,1}列表应将新元素插入lst3.begin()之前的位置。为什么他们会得到相同的结果? 谢谢!

int main() {
    list<int> lst = {1,2,3,4};
    list<int> lst3;
    // copy(lst.cbegin(), lst.cend(), inserter(lst3, lst3.begin()));
    copy(lst.cbegin(), lst.cend(), back_inserter(lst3));
    for_each(lst.cbegin(), lst.cend(), [] (const int i) {cout<<i<<endl;});
    return 0;
}

3 个答案:

答案 0 :(得分:0)

std::inserter函数从传递给函数的参数中创建一个std::insert_iterator对象。

您遇到的问题是由于两件事:

  • 第一个是迭代器是复制
  • 第二个是当容器为空时,其begin迭代器等于其end迭代器。

因此std::insert_iterator对象将具有列表end迭代器的副本,因此插入列表的末尾。

由于您从现有列表的开头进行迭代,并且始终在最后插入,因此效果将与使用std::back_inserter完全相同,其中元素按迭代顺序插入。

答案 1 :(得分:0)

您所看到的行为对于std::inserter()是正确的。

您期望的行为 - 即始终在前面插入 - 是您使用std::front_inserter()获得的行为。

答案 2 :(得分:0)

  

应将新元素插入到lst3.begin()

之前的位置

你想象的相当于:

 copy(lst.cbegin()+0, lst.cbegin()+1, inserter(lst3, lst3.begin()));
 copy(lst.cbegin()+1, lst.cbegin()+2, inserter(lst3, lst3.begin()));
 copy(lst.cbegin()+2, lst.cbegin()+3, inserter(lst3, lst3.begin()));
 copy(lst.cbegin()+3, lst.cbegin()+4, inserter(lst3, lst3.begin()));

(假装那些+操作可以在列表迭代器上工作)

我明白为什么你会这么想,但不是。

当你向lst3.begin()提供inserter时,这个迭代器不会被存储/缓存并重复使用 - 我们知道它不可能,因为(考虑一般的情况;列表特别不容易这样做)这样的迭代器可能会被每个插入操作无效。

相反,迭代器在每次操作后递增。

cppreference explains this

  

插入序列容器时,插入点前进,因为每个std :: insert_iterator :: operator =更新目标迭代器

事实上,我们可以从the cppreference insert_iterator::operator= page中看到这一点。

最终结果是你实际上是以线性,从左到右的顺序插入,如:

 copy(lst.cbegin()+0, lst.cbegin()+1, inserter(lst3, lst3.begin()));
 copy(lst.cbegin()+1, lst.cbegin()+2, inserter(lst3, lst3.begin()+1));
 copy(lst.cbegin()+2, lst.cbegin()+3, inserter(lst3, lst3.begin()+2));
 copy(lst.cbegin()+3, lst.cbegin()+4, inserter(lst3, lst3.begin()+3));

(假装那些+操作可以在列表迭代器上工作)

这种行为实际上更直观; 整个源范围已按其原始顺序插入到lst3.begin()开头的位置。