2

我有以下代码:

#include<iostream>
#include <vector>
using namespace std;
template<class T>
class Stack
{
private:
    vector<T> stack;

public:
    T Pop()
    {
        if (stack.size()!=0)
        {
            T temp;
            temp=stack[stack.size()-1];
            stack.erase(stack.begin()+stack.size()-1);
            return temp;
        }
        else
                   //return nothing
                   ^^^^^^^^^^^^^^^^
                   //How i can do above by code    
    }

在弹出功能中:我想要 if stack.size==0; 弹出函数不返回任何内容

我该怎么做?

4

5 回答 5

5

这基本上是一个关于如何处理非全部函数的问题——这些函数不一定是为所有可能的输入定义的。有很多方法可以解决它,尽管它们都不是类型安全的:

  1. 有两个单独的函数用于检索和擦除堆栈的顶部元素,很像std::stack::top()std::stack::pop()

  2. 使用引用参数并返回一个bool指示是否返回元素:

    bool pop(T& value) {
      if (stack.empty())
        return false;
      value = stack.back();
      stack.pop_back();
      return true;
    }
    

    调用者可以写:

    T value;
    if (stack.pop(value)) {
      use(value);
    }
    
  3. 返回一个boost::optional<T>

  4. 返回一个默认构造的T实例。这要求它T是可默认构造的,这已经由一些std::vector成员函数强加。

  5. 抛出异常,记录违反了先决条件。

  6. 未定义弹出空堆栈的行为。

我推荐 #1、#2 或 #3,具体取决于偏好和最适合周围代码的内容。

于 2013-04-14T07:13:33.347 回答
2

您可能仍然希望以与 std::stack 相同的方式拆分为std::stack::topand std::stack::pop。你不想pop返回一个值。

这是来自http://cpptruths.blogspot.com.au/2005/10/why-does-stdstackpop-returns-void.html的解释

http://www.sgi.com/tech/stl/stack.html解释

[3] 有人可能想知道为什么 pop() 返回 void 而不是 value_type。也就是说,为什么必须使用 top() 和 pop() 来检查和删除顶部元素,而不是将两者组合在一个成员函数中?事实上,这种设计是有充分理由的。如果 pop() 返回顶部元素,它必须按值而不是按引用返回:按引用返回会创建一个悬空指针。然而,按值返回是低效的:它涉及至少一个冗余的复制构造函数调用。由于 pop() 不可能以既高效又正确的方式返回一个值,所以更明智的是它根本不返回任何值并要求客户端使用 top() 来检查值栈顶。

std::stack < T > 是一个模板。如果 pop() 返回顶部元素,则根据上述说明,它必须按值而不是按引用返回。这意味着,在调用方,它必须被复制到另一个 T 类型的对象中。这涉及复制构造函数或复制赋值运算符调用。如果这种类型 T 足够复杂并且在复制构造或复制分配期间抛出异常怎么办?在这种情况下,右值,即栈顶(按值返回)就简单地丢失了,并且没有其他方法可以从栈中检索它,因为栈的弹出操作已成功完成!

实践方法是一起使用pop(), top(), empty()

T top()
{
   return stack[size()-1];
}

void pop()
{
   stack.erase(stack.begin()+stack.size()-1);
}

用法:

if (!stack.empty())
{
    T t = top();
    pop();
}
于 2013-04-14T07:00:14.037 回答
1

有几种选择。一种是返回一个T使用标准构造函数构造的实例:

return T();

另一种方法是返回一个特殊的哨兵包装对象,它可以隐式转换为T,并有一个比较运算符,以便用户可以检查它。

于 2013-04-14T06:48:25.213 回答
1

您还可以执行一些操作,例如将 pop 方法声明为 void 甚至更好,bool 以获取操作的状态并通过引用将 T 类型作为参数传递,以便将结果存储在其中:

bool Pop (T& item)
{
    if (stack.size() != 0)
       {
           // your code
           item = temp; // you can even use item instead of temp from the begining

           return true;
       }
    return false;
}
于 2013-04-14T07:08:24.967 回答
1

这是执行此操作的一种方法。这个想法是将布尔标志与结果一起打包在一个元组中。该标志指示是否有结果。请注意,当前的实现要求 T 是默认可构造的。

template<class T>
class Stack
{
private:
    std::vector<T> stack;

public:
    typedef std::tuple<bool, T> return_t;

    void Push(const T& t)
    {
        stack.push_back(t);
    }

    return_t Pop()
    {
        if (stack.size()!=0)
        {
            T temp;
            temp=stack[stack.size()-1];
            stack.erase(stack.begin()+stack.size()-1);
            return std::make_tuple(true, temp);
        }
        else
            return std::make_tuple(false, T());
    }
};
int main()
{
    Stack<int> my_stack;
    bool has_result;
    int result;

    my_stack.Push(5);
    std::tie(has_result, result) = my_stack.Pop();
    std::cout << "has result = " << has_result << "\n";
    std::cout << "result = " << result << "\n";

    std::tie(has_result, result) = my_stack.Pop();
    std::cout << "has_result = " << has_result << "\n";
}
于 2013-04-14T07:12:16.450 回答