【问题标题】:size() Vs empty() in vector - why empty() is preferred?向量中的 size() 与 empty() - 为什么首选 empty()?
【发布时间】:2009-04-13 06:38:13
【问题描述】:

在调试某些东西时,我看到了 STL vector::empty() 实现:

bool empty() const
        {return (size() == 0); }

我相信,每当我们探测向量的空性时,总是建议使用空而不是 size()。但是看到这个实现,我想知道,这样做有什么好处?相反,在调用 empty 时会产生函数调用开销,因为它在内部调用 size()==0。

我认为 empty() 在列表的情况下可能会有所帮助,因为 size() 不能保证列表中的恒定时间。为了验证我的假设,我检查了列表实现,令人惊讶的是,在列表中也发现了相同的实现,

return (size() == 0);

我现在有点困惑。如果 empty 内部使用 size() 那么我们为什么更喜欢 empty 而不是 size() ?

【问题讨论】:

    标签: c++ stl size


    【解决方案1】:

    因为如果从 std::vector 切换到 std::list 或者其他容器,可能会不一样。

    例如,std::list::size 的某些实现采用 O(n) 而不是 O(1)

    【讨论】:

    • 确实如此。我想补充一点,这在编写通用代码并且您不知道实际使用的是哪个容器时很有用。
    • 这正是原因,size() 应该是一个恒定时间操作,但标准允许实现者有一个非常量时间实现。另一方面,empty()必须所有实现中是一个常数时间操作。
    • 当然,如果你决定从std::vector 切换到std::list 之类的东西,你会遇到很多更大的问题。就像完全不同的迭代器失效规则一样。
    • 这个答案在 C++03 中是正确的。在 C++11 中,size 必须是常数时间。
    • @BillyONEal 对。那么选择黑白 container.size() > 0!container.empty() 现在是风格问题了吗?我个人更喜欢后者,因为它更明确地说明了意图/可读性。
    【解决方案2】:

    您需要在每次使用size() 时写出条件。使用empty()很方便。当然,前提是您不切换容器。正如其他人所指出的,是否在empty() 中使用size() 取决于实现。但是,该标准确实保证:empty() 是所有 标准容器。

    【讨论】:

    • 这是唯一的区别吗?一个方便的因素
    • aJ:不,不仅仅是为了方便。阅读其他两个 cmets(包括我的)。
    • 同意。关于客户端代码,是的,使用空编写通用代码是有意义的。我对在 empty 中使用 size 的 STL 内部实现有点困惑。
    • @aJ:这是 Scott Meyers,Effective STL 中的项目之一。
    • 好的,我会检查的。感谢您的信息。
    【解决方案3】:

    嗯,正如您所说,这只是一个实现细节。 std::list 可以使用存储大小(恒定时间 size() 但线性时间 splice())或不使用(恒定时间 splice() 但线性时间 size())来实现。通过选择使用empty(),您可以避免在不需要知道大小的情况下押注于实现细节。

    【讨论】:

      【解决方案4】:

      按照标准,应首选 empty(),因为它具有恒定的时间复杂度,与容器类型无关。

      在 C++03 标准中,第 23.1 章,表 65:容器要求

      Operation:   empty()
      Return_type: convertible to bool
      Semantics:   equivalent to size()==0
      Complexity:  constant
      

      似乎在您的 STL 实现中,他们将语义视为真正的实现而忽略了复杂性要求,或者 size() 是实现中的常量时间(存储字段)。

      如果 size() 不是恒定时间,请联系您的供应商以了解 std::list::empty() 不满足标准容器要求。

      【讨论】:

      • 我认为没有任何确凿的证据表明他的 STL 实现不符合标准。标准甚至说 size() 应该是所有容器的常量时间,包括列表。
      • 我编辑了帖子的最后一部分,但忘记更新顶部。
      • 我不确定,但 sgi STL 网站将 empty() 描述为具有不定的常数时间复杂度。而 c++ 标准确实将其描述为具有恒定的时间复杂度。因此,我认为不要混合“STL”和“标准 C++ 库”很重要。两者都不是另一个的子集。
      • 或者如果说 STL 应该说一个是指 STandardc++Library 而不是 StandardTemplateLibrary 。我发现它经常混合:)
      • 如果您查看我的答案,当我指的是标准 c++ 库时,我从不说 STL,因为它只会引起混淆。例如,为什么不应该将 std::cout 包含在 STL(Standardc++Library)中?因此,如果有人说 STL 并包含 coutinto 它,其他人可能不会包含它。然后出现混乱:)
      【解决方案5】:

      第一,当您想知道某物是否为空时,使用名为empty() 的函数可以使代码更具可读性,这意味着您不必担心实现细节。这也意味着您的代码可以更容易地适应具有其他特性的其他类型的容器。

      第二,这只是一个 STL 实现。 我的 GNU C++ 看起来像这样:

      bool
      empty() const
      { return begin() == end(); }
      

      这最终会导致指针比较,而使用 size() 会导致减法(在此实现中)。

      第三,它不太可能产生额外函数调用的开销,因为empty()-函数可能是内联的(在两种实现中)。

      【讨论】:

        【解决方案6】:

        empty() 对所有容器类都有 O(1) 的实现。 size() 只能为某些容器提供 O(n) 的实现;这就是为什么首选 empty() 的原因。

        【讨论】:

          【解决方案7】:

          除了上面给出的原因,它也可以说比 foo.size() == 0 和/或 !foo.size() 更清楚

          【讨论】:

          • 或者可以说不是。经过多年的使用,当我浏览代码时,有时我仍然觉得 alist.empty() 正在清空列表。我认为它应该被称为 is_empty() (就像 iostreams 中的 is_open() 一样)
          【解决方案8】:

          除了非常有效的可读性点之外,您所经历的只是一种特定实现的工件,而不是唯一可能的工件。

          也就是说,在向量和列表情况下,或者在任何其他容器中,都没有理由或要求根据 size() 来实现 empty()。如果有更好的替代方案,则应使用它们,除非库的作者不称职,或者更合理地说是懒惰。

          至于 list 和 size() 的 O(1)-ness 或缺少它,您应该考虑到 list 可能将 size() 实现为 O(1) 或 splice(),但不是两者(考虑原因是一个有趣的练习。)因此,在您的情况下,您检查的库可能已将 size() 实现为 O(1) (在这种情况下 splice() 将是 O(n)),因此可以实现empty() 在 size() 方面不牺牲性能,否则,这将是一个非常糟糕的库。

          【讨论】:

            【解决方案9】:

            比 size() 更喜欢使用 empty(),因为每个容器可能以不同的方式实现 empty() 来获得恒定时间操作。

            示例:

            vector 实现为: 布尔空()常量 { // 测试序列是否为空 返回(大小()== 0); }

            列表实现为:

                    bool empty() const
                {   // test if sequence is empty
                return (_Mysize == 0);
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-04-06
              • 1970-01-01
              • 1970-01-01
              • 2011-03-06
              • 1970-01-01
              • 2011-11-03
              • 2019-04-15
              相关资源
              最近更新 更多