繁体   English   中英

std :: vector :: insert vs std :: list :: operator []

[英]std::vector::insert vs std::list::operator[]

我知道std::list::operator[]没有实现,因为它有糟糕的性能。 但是std::vector::insert它和std::list::operator[]一样低效。 背后的解释是什么?

std::vector::insert是因为std::vector必须满足SequenceContainer概念的要求,而任何概念(我所知道的)都不需要operator[] ,可能会在c +中的ContiguousContainer概念中添加+17。 因此operator[]添加到可以像数组一样使用的容器中,而insert是接口规范所必需的,因此符合某些概念的容器可以用于通用算法。

我认为斯拉瓦的答案做得最好,但我想提供一个补充说明。 通常使用数据结构,访问比插入更常见,反之亦然。 有许多数据结构可能试图以插入为代价来优化访问,但反之则更为罕见,因为它在现实生活中往往不太有用。

operator[] ,如果为链表实现,则可能会访问现有值(类似于它对vector )。 insert添加新值。 如果随后的访问非常快,那么你很可能会愿意在一个vector插入一些新的元素。 在许多情况下,元素插入可以完全在关键路径之外,而关键路径由单个遍历或已经存在的数据的随机访问组成。 因此,在这种情况下让insert处理细节非常方便(实际上有效且正确地编写它有点烦人)。 这实际上是一个非常罕见的矢量使用。

另一方面,在链表上使用operator[]几乎总是表明您使用的是错误的数据结构。

std::list::operator[]需要进行O(N)遍历,并且实际上并不符合list的设计要求。 如果需要operator[]则使用不同的容器类型。 当C ++民众看到[]他们假定为O(1)(或者更糟糕的是,O(Log N))操作。 list提供[]会破坏它。

但是虽然std::vector::insert 也是 O(N),但它可以进行优化:通过使vector的容量以大块增长,可以很容易地优化端点插入。 中间插入需要逐个元素移动,但在现代芯片组上也可以非常快速地执行。

[]运算符继承自普通数组。 它一直被理解为底层容器的快速(子线性时间)访问器。 由于list不支持子线性时间访问,因此实现运算符没有意义。

auto a = Container [10]; // Ideally I can assume this is quick

std::list <>::operator []的等价物是std::next <std::list<>::iterator> 记录在cpp-reference

auto a = *std::next (Container.begin (), 10); // This may take a little while

这是容器的真正通用方式索引。 如果容器支持随机访问,则它将是恒定时间,否则它将是线性的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM