C++ ';pop()';堆栈为空时返回的方法?

C++ ';pop()';堆栈为空时返回的方法?,c++,c,data-structures,C++,C,Data Structures,可能重复: 在C++中设计堆栈时,当栈为空时,应该返回 POP()/St>>方法(或 Frror())>强>方法?以下哪种设计更好 抛出异常 未定义,但要求调用isempty()方法的用户在调用pop()之前进行检查 返回bool代码,同时使用额外的参数(引用)传递弹出的元素 定义唯一的空元素 好的,我发现我的问题不是很清楚,让我试着重写一下: 有一些数据结构可以基于链表实现,比如stack、queue,每个数据结构都有一个返回前端元素(或尾部)的方法 我想知道,在数据为空的情况下,设计这种

可能重复:

在C++中设计堆栈时,当栈为空时,应该返回<强> POP()/St>>方法(或<强> Frror())>强>方法?以下哪种设计更好

  • 抛出异常
  • 未定义,但要求调用isempty()方法的用户在调用pop()之前进行检查
  • 返回bool代码,同时使用额外的参数(引用)传递弹出的元素
  • 定义唯一的空元素

  • 好的,我发现我的问题不是很清楚,让我试着重写一下:

    有一些数据结构可以基于链表实现,比如stack、queue,每个数据结构都有一个返回前端元素(或尾部)的方法

    我想知道,在数据为空的情况下,设计这种方法是否有原则性的指导原则


    我的定义是“使用方便,使用不当”。

    < P> C++的STL StALWALL不返回任何通过“代码> POP())/代码>,因为它解耦返回对象的值,实际上从堆栈的内部数据结构中弹出对象,使它们成为两个独立的函数。这是在设计堆栈数据结构时考虑的另一个选项。 对于这些类型的数据结构,您的第三个选项也是一种非常惯用的方法


    对于第四个选项,而不是“唯一的空元素”,我实际上会在第三个选项上做一个变体,其中,
    pop()
    函数采用指针参数而不是引用类型,如果堆栈中没有对象,则返回NULL。

    按约定编程的风格是,具有非空堆栈是调用
    pop
    的先决条件,并且在不满足其先决条件的情况下调用方法会产生未定义的结果。我的实现将抛出一个
    std::logic_错误
    ,但这不是必需的。在C中,我的实现将通过
    assert
    中止


    pop
    的调用方负责在调用
    pop
    之前确保堆栈不为空的前提条件成立。因此,堆栈应该有一个
    isEmpty
    方法供调用方检查。

    要在哪个环境类型中运行代码?通常情况下,与现有的行为模式相匹配要比完全按照自己的方式做事要好得多

    当您从空的抽象列表中请求元素时,它是否会引发异常?如果是这样的话,最好让弹出非完整堆栈引发异常

    当定义行为非常容易时,未定义的行为是一个错误的选择

    如果大多数代码通过return语句返回项,那么返回一个控件(bool表示它是否工作)是一个糟糕的设计。如果大多数代码通过参数列表返回项,那么通过return语句返回控件是一个很好的设计,前提是对类似集合的其他调用也这样做

    空元素没有多大意义,它变成了一个神奇的值。例如,如果我创建一个列表并在其中推送五个空元素,它是否与没有空元素的列表相同?它是否与包含一个空元素的列表相同?列表中有一些元素和一个空元素是一样的吗?空列表作为“特殊”对象是一回事,但是空元素是有问题的,因为它们并不真正包含元素的行为,而是包含列表的行为。良好的对象定向将行为的内容封装在它所描述的同一对象中

    请注意,空元素与哨兵不同。Sentinel是包含在集合中的实现细节(理想情况下永远不应该对外公开)。当我读到“returnsanempty元素”时,我认为人们必须非常了解堆栈的实现才能使用它。类之间过多的亲密关系称为紧密耦合,这会使代码更难继续修改/修复/更改


    如果您确实以自己的方式做事,那么您应该尽量使代码的整个方面都保持一致。它使维护更容易阅读。

    我建议同时使用
    pop
    trypop
    方法
    pop
    只需调用
    trypop
    并在失败时抛出异常。我的推理是,对于堆栈的某些使用,当堆栈为空时尝试弹出表示程序逻辑错误,这是不应该发生的-推送/弹出不平衡,或者由于资源耗尽而错误处理先前的推送失败。对于其他用途,无法弹出仅意味着您处于输入的末尾。当使用带有异常的编程模型时,区分这些用法可以避免在执行空堆栈检查和抛出异常时给调用者造成混乱。

    具有以下设计说明:

    有人可能想知道为什么pop()返回void,而不是value\u type。那个 问题是,为什么必须使用top()和pop()来检查和移除顶部 元素,而不是在单个成员函数中组合这两个元素?在里面 事实上,这种设计有很好的理由。如果pop()返回 元素,它必须按值返回,而不是按 引用:通过引用返回将创建一个悬空指针。返回 然而,按值计算是低效的:它至少涉及一个冗余 复制构造函数调用因为pop()不可能返回 以一种既高效又正确的方式来衡量价值,它更重要 明智的做法是完全不返回任何价值,并要求客户 使用top()检查堆栈顶部的值

    SGI进一步指定pop()