这是一个纯理论问题,我知道标准容器界面现在不太可能改变......
我最近读了一本Herb Sutter“本周的大师”,他抱怨说empty()在std::string
中被实现为成员函数。我不同意所有的论点,因为例如std::list
需要对同一函数执行不同的实现,因为size()
是O(n),而empty()
显然是O(1)。
但是,有没有理由为什么标准指定(例如)std::string
的empty()成员函数实现为"size () == 0"
而不是"begin () == end ()"
?
在我看来,后者允许对所有容器使用empty()
函数的相同O(1)实现,我想不出任何缺点。它的效率会降低吗?
谢谢,
N.G。
答案 0 :(得分:4)
标准未指定完全库中的任何内容的实现方式。它只是指明某事物的含义。因此,如果empty()
为真,则size()
也必须为0.这并不意味着empty()必须实际调用std::basic_string::size()
并将其与0进行比较。规范只是说如果empty()
返回true,则紧接着调用size()
将返回0,如果empty()
返回false,则在<{1}}之后立即调用<{1}} em> not 返回0。
规范可以说它的size()
将等于它的begin()
,并且它会迫使没有实现更改。
不一致很可能是end()
类在C ++ 98开发过程中来自其他STL容器的不同位置的结果。这就是为什么它有很多成员函数来处理STL容器通常用算法做的事情。
答案 1 :(得分:2)
empty()
与size() == 0
等效的规范不应按字面意思理解。代码片段仅显示函数的意图,而不是它们的实现方式。
我在另一个论坛上向委员会成员证实了这一点。
在您的示例中,size()
也可能实现为end() - begin()
的等效项,因此无论如何都可能没有区别。
答案 2 :(得分:0)
是的,因为string :: end()通常被实现为像return (_STRING_ITERATOR(_Myptr() + this->_Mysize));
因此,使用size()== 0可以减少添加的需要。
答案 3 :(得分:0)
Herb建议使length()
使用size()
实现非成员函数,并与empty()
等效:
长度()怎么样?容易,再次 - 它被定义为给出与size()相同的结果。更重要的是,请注意其他容器没有length(),并且它在basic_string接口中作为一种“字符串事物”存在,但是通过使它成为非成员突然我们可以简单地说“length()”关于任何容器。在这种情况下不太有用,因为它只是size()的同义词,我授予你,但它所说明的原则中值得注意的一点 - 立即使算法非成员也使它们更有用和可用。
size()
作为成员函数的原因是,在大多数情况下,实现将缓存计算成本高昂的容器的值(即对于列表或映射,存储包含的元素的数量在容器本身以避免必须走结构),以符合size
应该是O(1)
操作(§23.1/ 5)的标准中的建议。