如何在具有返回类型的函数中返回None?

时间:2013-04-14 06:38:35

标签: c++

我的代码如下:

#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    
    }

在pop功能中:我想要stack.size==0;弹出功能什么都不返回

我怎么做?

5 个答案:

答案 0 :(得分:5)

这基本上是一个如何处理non-total functions的问题 - 不一定为所有可能的输入定义的函数。有很多方法可以实现,但它们都不是类型安全的:

  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. 保持弹出空堆栈的行为未定义。

  7. 我建议#1,#2或#3,具体取决于偏好以及最适合周围代码的内容。

答案 1 :(得分:2)

您可能仍希望以与分割为std::stack::topstd::stack::pop的std :: stack相同的方式执行操作。您不希望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&lt; T>是一个模板。如果pop()返回顶部元素,则必须按值返回,而不是按照上述说明返回。这意味着,在调用者端,它必须被复制到另一种T类型的对象中。这涉及复制构造函数或复制赋值操作符调用。如果这种类型T足够复杂并且在复制构造或复制分配期间抛出异常怎么办?在这种情况下,rvalue,即堆栈顶部(由值返回)只是丢失,并且没有其他方法可以从堆栈中检索它,因为堆栈的弹出操作已成功完成!

实践方法是同时使用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();
}

答案 2 :(得分:1)

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

return T();

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

答案 3 :(得分: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;
}

答案 4 :(得分: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";
}