为什么 std::list.size() 不是恒定时间?
Why isn't std::list.size() constant-time?
此代码运行0.012秒:
std::list<int> list;
list.resize(100);
int size;
for(int i = 0 ; i < 10000; i++)
size = list.size();
这是9.378秒:
std::list<int> list;
list.resize(100000);
int size;
for(int i = 0 ; i < 10000; i++)
size = list.size();
我认为,可以以这种方式实现std ::列表,该大小将存储在私人变量中,但根据此,每次我调用大小时都会再次计算。谁能解释为什么?
恒定时间size()
与恒定时间list.splice
之间存在冲突。委员会选择赞成splice
。
当您在两个列表之间拼接节点时,您必须计算移动的节点以更新两个列表的尺寸。通过更改一些内部指针,这带走了剪接节点的很多优势。
正如评论中指出的那样,C 11通过放弃o(1)的 splice
使用(?)的使用来改变这一点。
void splice(const_iterator position, list& x, const_iterator first, const_iterator last);
void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);
复杂性:如果
&x == this
,则恒定时间;否则,线性时间。
在 ISO/IEC 14882:2011
,§c.2.12,第23条:"容器库":
更改:大小()成员函数的复杂性现在恒定
基本原理:缺乏大小()复杂性的规范,导致了具有不一致的性能特征的不同实现。
对原始功能的影响:符合C 2003的某些容器实现可能不符合本国际标准中指定的大小()要求。调整诸如STD ::列表之类的容器列表到更严格的要求可能需要不兼容的更改。
评论:
在23.3.5.5中 - "列表操作",再次在ISO/IEC 14882:2011
中:
列表提供了三个剪接操作,这些剪接操作将元素从一个列表转移到另一个列表。如果get_allocator()!= x.get_allocator()。
void splice(const_iterator位置,列表&amp; x);
void splice(const_iterator位置,列表&amp; x);
需要:&amp; x!= this。
效果:插入位置之前的X内容,X变为空。指针和提及X的移动元素现在指的是相同的元素,但是 *此元素。迭代器引用移动元素将继续提及其元素,但现在它们以迭代剂的形式行为 *,而不是x。
。 复杂性:恒定时间。void剪接(const_iterator位置,列表&amp; x,const_iterator i);
void splice(const_iterator位置,列表&amp; x,const_iterator i);
效果:插入i在位置之前从列表x指向的元素,然后从x中删除元素。如果位置== i或位置== i,则结果是不变的。指针和引用 *我继续指代相同的元素,但作为 *的成员。迭代器 *i(包括i本身)继续指的是相同的元素,但现在以迭代剂的形式行为 *,而不是x。
需要:我是X。
的有效解释迭代器 复杂性:恒定时间。void splice(const_iterator位置,列表&amp; x,const_iterator first,const_iterator last);
void splice(const_iterator位置,列表&amp; x,const_iterator first,const_iterator last);
效果:在位置之前将元素插入[首先,最后一个),然后从x中删除元素。 需要:[第一个,最后一个)是x中的有效范围。结果如果位置是该范围内的迭代器,则结果是不确定的。指针和提及X的移动元素现在指的是相同的元素,但是 *此元素。提到移动元素的迭代器将继续指向其元素,但是现在它们以迭代器的形式行为 *,而不是x。
。 复杂性:如果&amp; x == this;否则,线性时间。
- 如何将 STL 队列推送函数绑定到 std::函数?
- 如何将 std::将结果绑定到 std::function
- 错误:无法将"std::istream {aka std::basic_istream<char>}"lvalue 绑定到"std::basic_istream&<char>&
- 错误:无法将"std::ostream {aka std::basic_ostream<char>}"lvalue 绑定到"std::basic_ostream&<char>&
- rvalue参考绑定到std ::功能类型的LVALUE
- high_resolution_clock错误:无法将"std::ostream {aka std::basic_ostream}"<char>lvalue 绑定到"std::basic_
- 错误:无法将"std::<char>basic_ostream"左值绑定到"std::basic_ostream<char>&&"
- 模板变量的绑定时间
- 将带有unique_ptr参数的函数绑定到 std::function<void()>
- std::绑定到std::函数
- 将临时右值绑定到 std::vector 构造函数中的引用左值
- 绑定到 std::operator== 时未解决的重载函数错误
- 将常规函数绑定到 std::function
- 重载运算符<<:无法将左值绑定到"std::basic_ostream<char>&&"
- 编译错误无法将'std::basic_ostream<char>' lvalue 绑定到'std::basic_ostream<char>&&'
- 无法正确地向java绑定公开std::pair
- 执行绑定的 std::函数会抛出 std::bad_function_call
- 如果自定义分配器中没有重新绑定,std::allocator_traits是否定义了rebind_alloc ?
- 如何在Visual Studio 11中直接将成员函数绑定到std::函数
- 将指向成员函数的指针绑定到std::pair并强制转换为void*