【发布时间】:2010-09-20 08:09:36
【问题描述】:
std::string size() 是 O(1) 运算吗?
我使用的 STL 的实现是 VC++ 内置的
【问题讨论】:
标签: c++ visual-c++ stl stdstring
std::string size() 是 O(1) 运算吗?
我使用的 STL 的实现是 VC++ 内置的
【问题讨论】:
标签: c++ visual-c++ stl stdstring
size_type __CLR_OR_THIS_CALL size() const
{ // return length of sequence
return (_Mysize);
}
所以最终可能会是这样,但你永远无法确定。
【讨论】:
是的,std::string::size() 是 O(1)。
【讨论】:
STL 保证容器的性能至少为 O(N),但是包括 std::string 在内的许多容器可以将其实现为 O(1) 并且将。通常它要么返回一个简单的变量,要么执行 _End - _Begin 之类的操作并返回它。
【讨论】:
请参阅标准第 23.1 节中的表 65。 “a.size()”被列为“(注 A)”,表示“那些条目......应该具有恒定的复杂性”。
第 21.3 节说字符串符合序列 (23.1) 的要求,事实上,size() 是常数时间。
【讨论】:
如果您要问 MSVC 的 string::size() 实现是否具有恒定的复杂性,那么答案是肯定的。但是Don Wakefield 提到了 C++ 标准 23.1 中的表 65,它说size() 的复杂性应该遵循“注释 A”中所说的内容。注 A 说:
那些标有“(注 A)”的条目 应该具有恒定的复杂性。
但是,这并不意味着这些条目应该具有恒定的复杂性。标准使用非常具体的术语,“应该”意味着它不是强制性的。
在标准中添加了“注释 A”,以安抚那些认为应该允许 size() 具有线性复杂性的人,因此在修改容器时不必保持大小。
所以你不能依赖size() 具有恒定的复杂性,但老实说,我不确定是否有任何实现没有恒定的string::size()。
【讨论】:
(end() - begin())。这保证 [amortized] O(1),因为 begin() 和 end() 都必须是 O(1)(容器要求),字符串迭代器是随机访问的(字符串要求),并且 operator- 必须是 O (1) 对于支持它的迭代器(迭代器要求)。
O(1) 不是 所有 容器的要求这一事实并不意味着它可以是容器中的O(N),只是至少可以有一个容器是非常量的,例如std::list<>。
std::string 要求禁止这样做(例如,这似乎意味着数组下标不再是 O(1))。
std::basic_string<>::size() 时,它指的是容器要求(即建议的常量大小),在 11 标准中,要求是明确的:复杂性:常量时间。
basic_string符合序列的要求,如(23.1.1)中规定的那样”,序列是一种容器(23.1.1/1),并且容器要求恒定时间 begin() 和 end()(23.1 中的表 65)很高兴听到他们在 C++11 中明确表示。
这是为 msvc++ 回答该问题的一种简单方法。
在项目中编写一些代码:
string happy;
happy.size();
突出显示 .size 调用,右键单击,转到定义。
在我的安装 (vs2005sp1) 中,这会将我发送到 xstring:1635,如下所示:
size_type __CLR_OR_THIS_CALL size() const
{ // return length of sequence
return (_Mysize);
}
所以看起来字符串有一个名为 _Mysize 的成员,它只是返回它。
换句话说,这是一个 O(1) 的实现。
【讨论】:
对于字符串,size() 操作必须对于所有不使用 绳索(1) 的字符串实现都是常量.标准中没有明确要求要求操作为O(1),最接近的是size()应该是常数时间的通用要求,但这为任何其他复杂性度量留出了空间。
那么为什么必须是O(1)呢?
这是因为无法从字符串本身的内容计算大小。在 C 中,您使用 NUL 终止符来确定字符串的结尾,而在 C++ 中,NUL 与字符串中的任何其他字符一样有效。由于无法根据内容(2)计算字符串的大小,因此必须在外部处理,与字符串的实际大小无关。
(1) C++03 标准允许实现使用 ropes 作为字符串的实现,但事实是该标准的当前实现都没有图书馆使用它们。
(2) 如果实现使用绳索,则操作可能取决于大小,即构建绳索的块的数量(如果块通过链表或类似方式链接)构造,或者如果它们被允许具有不同的大小。但是 ropes 在我所知道的任何标准库实现中都没有使用。
【讨论】:
size() 的复杂性应该遵循“注 A”。这意味着,它应该具有恒定的复杂性,即 O(1)。虽然,我不确定实现,但 C++ 中的迭代器确实具有指向 STL 容器的关联操作,如 begin() 和 end()。这些操作具有恒定的时间复杂度,因为它们是容器要求。这意味着begin() - end() 也具有恒定的复杂性。也就是说,size() 是 O(1) 运算。
【讨论】: