【问题标题】:Why don't the standard C++ container adaptors provide a clear function?为什么标准的 C++ 容器适配器不提供明确的功能?
【发布时间】:2009-01-29 22:29:11
【问题描述】:

有谁知道为什么 std::queue、std::stack 和 std::priority_queue 不提供clear() 成员函数?我必须像这样伪造一个:

std::queue<int> q;
// time passes...
q = std::queue<int>();  // equivalent to clear()

IIRC,clear() 由所有可以用作底层容器的东西提供。是否有充分的理由不让容器适配器提供它?

【问题讨论】:

    标签: c++ stl standards


    【解决方案1】:

    嗯,我认为这是因为clear 未被视为对队列、priority_queue 或堆栈的有效操作(顺便说一下,deque 不是适配器,而是容器)。

    使用容器的唯一原因 适配器队列而不是容器 deque 是为了表明你是 仅执行队列操作,并且 没有其他操作。 (from the sgi page on queue)

    所以当使用队列时,你所能做的就是推送/弹出元素;清除队列可以看作是对 FIFO 概念的违反。因此,如果您需要清除队列,可能它并不是真正的队列,您最好使用双端队列。

    不过,这种想法有点狭隘,我觉得像你这样清队列也够公平的了。

    【讨论】:

      【解决方案2】:

      双端队列有 clear()。参见,例如,http://www.cplusplus.com/reference/stl/deque/clear.html

      但是,队列没有。但是你为什么要选择队列而不是双端队列呢?

      使用容器的唯一原因 适配器队列而不是容器 deque 是为了表明你是 仅执行队列操作,并且 没有其他操作。

      (http://www.sgi.com/tech/stl/queue.html)

      那么我猜 clear() 不是队列操作。

      【讨论】:

        【解决方案3】:

        我会说这是因为容器适配器不是容器。

        【讨论】:

          【解决方案4】:

          您可以清除队列(以及 std::stack 和 priority_queue),只要您从它继承即可。容器故意受到保护以允许这样做。

          #include <queue>
          
          using namespace std;
          
          class clearable_queue : public queue<int>
          {
          public:
            void clear()
              {
                // the container 'c' in queues is intentionally left protected
                c.clear();
              }
          };   
          
          int main(int argc, char** argv)
          {
            clearable_queue a;
            a.clear();
          }
          

          【讨论】:

          • 你不应该从标准容器公开继承,即使你不添加实例变量:通过没有虚拟析构函数的基类指针删除派生类将导致未定义的行为(它是 保证调用基类析构函数)。
          【解决方案5】:

          我认为这取决于实施 - 直到最近 Microsoft STL 还没有明确几个容器。 (现在可以了,例如this quick google result

          然而,clear() 通常只是对 erase(begin(), end()) 的调用,因此请实现您自己的等价物并改用它。

          我认为标准将 clear 称为在迭代器范围内擦除,所以以上是大多数实现将提供的。 (eg Dinkumware's)

          【讨论】:

          • stack、queue 和 priority_queue 也没有迭代器。
          【解决方案6】:

          std::queue、std::deque 和 std::priority_queue 是容器适配器,只提供少量方法来访问底层容器。

          您可以清除底层容器,只要您可以访问它。为此,请创建底层容器以传递给 apadptor 构造函数。例如:

          std::deque< int > d;
          std::queue< int > q( d );
          
          ... time passes ...
          
          d.clear();
          

          编辑:附加信息

          我还应该警告您在这里小心行事,因为在底层容器上调用方法可能会破坏适配器所做的假设。在这方面,您当前清除队列的方式似乎更可取。

          【讨论】:

          • Daniel,这是不正确的,队列的构造函数参数仅用于初始化队列,而不用于传递对实际容器的引用。换句话说,'q' 将使用 'd' 的内容进行初始化,但清除 'd' 不会影响 'q'。
          • 有趣 - 我查看的构造函数没有对集合进行 const 引用...
          • 再试一次 - 你是对的。适配器将集合保存为值,而不是引用,并且适配器的构造函数获取对集合的 const 引用以进行初始化。有趣的是,在VS2008中,队列的“c”成员是公开的!它在 priority_queue 中受到保护。
          猜你喜欢
          • 2012-08-07
          • 1970-01-01
          • 2011-04-21
          • 2020-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-31
          相关资源
          最近更新 更多