C++中"机械臂"的机制是什么?

What's the mechanism of `inserter` in C++?

本文关键字:机制 是什么 机械 C++      更新时间:2023-10-16

我尝试了代码吹气,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;
}

元素应该插入到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()));

(假装这些+操作将在列表迭代器上工作)

我明白你为什么会这么想,但没有。

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

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

CPP偏好对此进行了解释:

插入

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

事实上,我们可以从 cpp首选项insert_iterator::operator=页面中亲眼看到这一点。

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

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()开头的位置。

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

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

@Lightness Races in Orbit的答案是正确的。

简而言之,std::inserter(container, iterator_argument)始终绑定到最初传入的iterator_argument位置。

例如:

vector<int> vec = {1,2,3,4};
auto it = std::inserter(vec, vec.begin() + 1);

内部状态:

1,2,3,4
↑
it

插入一个元素:

*it = 888;

内部状态:

1,888,2,3,4
↑
it

插入一个元素:

*it = 999;

内部状态:

1,888,999,2,3,4
↑
it

所以你不会得到一个相反的顺序序列。

顺便说一句,对于std::inserter,您只需要继续执行插入*it = valueit++++itstd::inserter没有影响.这个位置是永远绑定的。


另请查看文档:

https://en.cppreference.com/w/cpp/iterator/insert_iterator/operator=

1) 结果iter = container->insert(iter, value); ++iter;

那么container->insert(iter, value);的价值是什么?

它:

https://en.cppreference.com/w/cpp/container/vector/insert

1-2) 指向插入值的迭代器

std::inserter

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

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

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

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

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