关于STL的stack的疑问

qiaojicheng 2003-12-29 09:01:24
我使用的是VC自带的STL,它里面堆栈的实现代码中pop这样定义:
void pop();
而另外定义了一个 value_type& top();
为什么不像常规那样pop返回一个值呢?这样定义很不习惯,要先取值,再弹出,很容易忘记弹出操作呀!
...全文
266 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
hz129 2003-12-30
  • 打赏
  • 举报
回复
我在linux g++3.2.2下运行,底层容器不同结果也不同,以deque和vector为底层容器时,栈空时top调用导致段错误。以list为底层容器时top调用返回0。
栈top()会调用底层容器的back()操作,deque和vector为空时,back()操作会使用空指针,而list为双向循环链,有一个作为链头的标志块,所以调用back()是不会导致空指针操作。但执行pop()操作时会出错。
#include <stack>
#include <list>
#include <iostream>
using namespace std;

int main() {
stack< int, list<int> > s;
cout << "s.top()=" << s.top() << endl;
s.pop();
}

STL对空栈调用top和pop应该是未定义的,可能设计者认为使用STL的人应该知道自己在做什么,如果想要比较安全的使用,可能JAVA的异常机制会更理想一些。
qiaojicheng 2003-12-30
  • 打赏
  • 举报
回复
古雨:
对于top,是必须的,有些实现使用peek(一瞥),很形象,和pop加以区分;

对于pop,谢谢你的解释,我没有考虑到构造和拷贝的开销。

还有一个问题,栈空时top的调用会导致什么结果?
hz129 2003-12-30
  • 打赏
  • 举报
回复
我觉得可以从效率方面考虑:
首先value_type& top();这个函数是不可少的。
对于pop,需要将栈顶元素弹出,定义为value_type& pop()显然是不合适的。因为如果返回的是个引用,则栈顶元素不能被析构,此时又不能保证返回值会被应用,那么这个元素的析构时机就没法确定了,极有可能造成内存泄漏,如果改为value_type pop(),则在返回值不被使用的时候,平白无故的多用了一次拷贝构造函数,这与STL对效率的追求是相悖的。而分为两个函数,可以让使用者决定是否需要这个拷贝构造,最大化了效率。
eg:
X& a = XStack.top();
...
XStack.pop(); // 此时a将失效

X a = XStack.top();
...
XStack.pop(); // a仍然有效,执行赋值时会调用拷贝构造函数
qiaojicheng 2003-12-30
  • 打赏
  • 举报
回复
xiaocai365(小菜)
我是说我设计的话就让它抛出一个异常,STL确实没有这样做。
之所以抛出异常是因为当使用者不合理的使用时给他一个提示,本来就应该先检查栈是否为空的。
STL在栈空时什么反应都没有,岂不是更不容易调试的时候发现问题,使用者也就很容易忘记检查了。
Robin 2003-12-29
  • 打赏
  • 举报
回复
按照你的思路的话,假如Clients继承了她之后,也许会出现这中情况!
Robin 2003-12-29
  • 打赏
  • 举报
回复
stephenland74(程序员)说的也有道理!
如果出现了Exception,在函数内部抛出Exception,也许会给大家造成更大的疑惑!
这样做的话,让我们自己来检测Exception!
Robin 2003-12-29
  • 打赏
  • 举报
回复
为了最大程度的满足用户的需要!
这两个Interface的意义是什么呢!


xiaocai365 2003-12-29
  • 打赏
  • 举报
回复
qiaojicheng(乔)
标准库中的stack在pop下溢时无定义,而不是抛出异常。
抛出异常的代价就会高一些。

话说回来pop下溢的确是可以防护的,不过以上这些思考,恰好说明了标准库中的设计比较简单。
stephenland74 2003-12-29
  • 打赏
  • 举报
回复
因为要保证操作的原子性,如果top和pop一样,当pop操作发生异常的时候,top并没有使栈顶的指针减一,而此时函数就退出了,如果下一次的调用继续的话,该栈的指针就会永远错下去,也许这个问题并不是很难解决,但只是这样的解决方法,会引发一些不合理的代码,而求在类的设计上也是一个隐患。
qiaojicheng 2003-12-29
  • 打赏
  • 举报
回复
xiaocai365(小菜)
pop之前应该查询是否为空,这样设计我也要查询呀,如果为空,就抛出一个异常,很正常呀!

Polarislee(北极星)
pop的语意就是弹出,返回栈顶值,搞成这样觉得很不习惯。
北极猩猩 2003-12-29
  • 打赏
  • 举报
回复
将查询与操作分离,最简单的思想。习惯就好了:P
xiaocai365 2003-12-29
  • 打赏
  • 举报
回复
对设计会有简化作用。
试想如果对空的栈 pop(),应该弹不出东西,
如果让你来设计 value_type& pop(),会怎样做。

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧