C ++ STL堆栈问题:如果堆栈为空,为什么pop()不会抛出异常?

时间:2011-02-03 21:46:07

标签: c++ exception stl stack

如果堆栈为空并且没有任何内容可以弹出,为什么std :: stack :: pop()不会抛出异常?

(我正在为自己的代码设计一个专用的堆栈,并且想知道这种方法的权衡(需要人们手动检查堆栈是否为空)而不是抛出异常。

我的猜测是,尽管C ++支持异常处理,但它带来了较小的运行时开销,因此,为了获得最大性能,决定不在std :: stack :: pop中引发异常。

6 个答案:

答案 0 :(得分:12)

我认为pop()不必抛出异常 nothing 与效率或性能有关,但是 - 例外。

正如所说elsewhere

  
      
  1. SGI解释:http://www.sgi.com/tech/stl/stack.html   有人可能想知道为什么pop()会返回   void,而不是value_type。那是,   为什么必须使用top()和pop()来实现   检查并删除顶部元素,   而不是将两者结合在一起   单一成员功能?事实上,那里   是这个设计的一个很好的理由。如果   pop()返回顶部元素,它   必须以价值回报   而不是通过引用:通过引用返回   会创造一个悬垂的指针。   然而,按价值返回   效率低下:它涉及至少一个   冗余复制构造函数调用。以来   pop()不可能返回一个   价值以两者兼顾的方式   高效和正确,更多   明智的是它没有回报价值   所有并要求客户使用   top()检查顶部的值   堆栈。

  2.   
  3. std :: stack< T>是一个模板。如果pop()返回顶部元素,那么   必须以价值回报   而不是按照上述参考   说明。这意味着,在来电者   它必须在另一个T中复制   对象的类型。这涉及一份副本   构造函数或复制赋值   操作员电话。如果这个类型T是什么   足够复杂,它抛出一个   复制建设期间的例外或   复制作业?在那种情况下,   rvalue,即堆栈顶部(返回   按价值而言,简直就是迷失了   没有其他方法可以从中检索它   堆栈作为堆栈的弹出操作   顺利完成!

  4.   

一旦我们得出结论,pop应该返回它弹出的元素,因此它的界面固定为void pop(),它 - 这是我的意见 - 对任何意义都没有任何意义规定在空堆栈上调用pop()时会发生什么。

请注意,标准需要!empty()作为调用pop()的前提条件。

UncleBens(在评论中)肯定有一点,即不在运行时检查前提条件(C ++标准AFAIK从未规定)具有一定的性能气味。但是,引用原始问题的一部分:(强调我的)

  

(我正在设计一个专门的Stack for   我自己的代码,想知道   与这种方法进行权衡(其中   需要一个人手动检查是否   堆栈是空的)与投掷   异常。

我会争辩说,pop()没有返回任何东西的事实使得这个问题没有实际意义。它(恕我直言)根本没有意义强制pop()验证堆栈是否为空,当我们真的没有从它得到任何回报时(即如果堆栈是空的pop()可以简单地是一个noop ,(诚然)也没有由Std规定。)

我认为可以问为什么top()不会抛出异常可以问为什么pop()不会返回顶部元素。如果pop没有返回任何内容,抛出一个异常没有意义(在C ++世界中) - 声称它不会抛出异常“因为异常的运行时成本”就像其他答案一样意味着 - 恕我直言 - 错过了重点。

答案 1 :(得分:8)

你是对的。 C ++标准始终优先考虑性能和安全性。但是可能存在包含调试范围检查的STL实现。

答案 2 :(得分:5)

与C ++中的几乎所有功能一样,它们是围绕您不为不使用的内容付费的概念而设计的。并非所有环境都支持异常,传统上,尤其是游戏开发。

因此,如果使用std :: stack强制使用异常将失败其中一个设计指南。即使禁用了异常,您也希望能够使用堆栈。

答案 3 :(得分:3)

我认为值得一提的是,如果堆栈为空,pop() 允许抛出 - 它只是不需要。在你的堆栈中,你可以assert堆栈不是空的,那就完全没问题了(空堆栈上的pop似乎给了UB,所以你可以做任何你想做的事情,真)。

答案 4 :(得分:2)

除了性能之外,我不认为从空堆栈中弹出是一种特殊情况 - 因此我也不会抛弃它。

答案 5 :(得分:1)

例外是可选的,STL希望随处可用。认为嵌入式系统:许多C ++代码,运行时没有异常支持。