[英]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.