【问题标题】:Stack combine both pop() and top()?堆栈结合了pop()和top()?
【发布时间】:2020-11-26 00:55:59
【问题描述】:

对于std::stack,我们使用pop() 提取最后一个成员并使用top() 获取其值。是否有任何捷径可以同时执行这两个操作(获取最后一个成员的值并将其踢出)?

【问题讨论】:

  • 简答,不。你必须处理空的情况(堆栈是空的)所以它并不简单
  • 另见Why doesn't std::queue::pop return value.?。嗯,锤还是不锤?
  • 不,在空堆栈上调用 top 或 pop 是不安全的。这样做会导致未定义的行为
  • @NathanOliver,因为无论如何它都是 UB,所以如果模仿 stack 要求,您不必担心这种情况。执行auto& elem = top(); pop(); return elem; 的实现将具有与top 相同的UB 特征。

标签: c++ stack std


【解决方案1】:

top() - 只返回元素但不删除它。 pop() - 只删除元素但不返回任何内容。

没有这样的方法可以删除并返回已删除的元素。

确保在执行 top 或 pop 时进行空检查,因为它会导致错误。在执行任何这些操作之前,请先进行空白检查。

【讨论】:

    【解决方案2】:

    有什么捷径可以同时做这两个动作

    没有。

    但是您可以编写一个调用两者的函数并将其用作您的“快捷方式”。

    【讨论】:

      【解决方案3】:

      这没有技术原因无法完成。它可以作为一个实用程序简单地实现:

      template <typename T>
      auto pop_value(T & stack) {
          auto v = std::move(stack.top());
          stack.pop();
          return v;
      }
      

      如果使用 C++11 且返回类型推导不可用,请将 auto 替换为 typename T::value_type

      【讨论】:

      • 就像std::move 的用法一样,很容易“忘记”top 返回一个引用(不是复制的值)
      • @ShmilTheCat 我不确定你在说什么。您是在指出我的代码中的一个缺陷,还是只是顺便观察一下为什么这种函数很有用?
      • 没有缺陷!只是强调了您的代码的有用性,以及您对 move 语义的细致使用,IMO 可能会被许多人忽视
      • 啊酷。我想我对您第一条消息中的“喜欢”感到困惑。我读了它“类似于std::move 的用法”并且无法弄清楚意思,但现在我认为您的意思是“我喜欢std::move 的用法”。请注意,如果不移动,此代码仍然是安全的,它只会制作冗余副本(并且根本不能用于不可复制的类型)。
      【解决方案4】:

      pop() 不返回弹出元素的值的原因是这样做不是异常安全的。如果返回值的复制构造函数抛出异常,则该值已丢失。它已从堆栈中删除,但尚未被复制。没有办法把它找回来。如果你不关心这个,你可以用显而易见的方式编写你的“快捷”函数:复制top()对象,pop()堆栈,然后返回值。

      【讨论】:

        猜你喜欢
        • 2016-08-16
        • 2013-04-20
        • 2010-09-30
        • 2023-04-01
        • 2016-10-24
        • 2019-02-06
        • 2011-05-04
        • 2016-10-23
        • 2012-08-26
        相关资源
        最近更新 更多