【问题标题】:Confused about returns in stack template对堆栈模板中的返回感到困惑
【发布时间】:2015-06-22 15:11:29
【问题描述】:

我正在用 C++ 实现一个通用堆栈(带有一个数组),并且对在这种情况下返回什么感到困惑:

template <class T>
T Stack<T>::pop(void) {
    if (size != 0) {
        return items[size - 1];
        size--;
    } else {
        cerr << "Cannot pop from empty stack." << endl;
        return ???;
    }
}

template <class T>
T Stack<T>::peek(void) {
    if (size != 0)
        return items[size - 1];
    else {
        cerr << "Cannot peek from empty stack." << endl;
        return ???;
    }
}

我在这里有什么选择?我认为做一些事情会很麻烦,比如声明一个新的 T 变量并返回它。我在画一个空白。

【问题讨论】:

  • 抛出异常?
  • 注意:return 之后的语句无法访问 - 具体来说,size--; 行将不会运行!
  • @SanderDeDycker 是的,那是个意外。已经修好了
  • std 实现抛出异常,您还可以返回 pairbool 以表示成功和实际元素(如果为空则默认构造)。另外,不要使用数组,使用vectordeque
  • @imreal。即使在容器的用户没有犯这个错误的情况下,这也会强制 T 成为默认可构造的。也许返回 pair&lt;bool, optional&lt;T&gt;&gt; 或类似的。

标签: c++ templates generic-programming


【解决方案1】:

这取决于您希望类的行为(协议)是什么。由于您正在那里登录错误流,我假设您认为这是在空堆栈上调用 pop() 的错误条件。发出错误信号的标准 C++ 方法是抛出异常。像这样的:

template <class T>
T Stack<T>::pop(void) {
    if (size != 0) {
        size--;
        return items[size];
    } else {
        throw std::invalid_argument("Cannot pop from empty stack.");
    }
}

另一种方法是说pop() 有一个前提条件“堆栈不为空”。违反先决条件通常是未定义的行为,因此您可以简单地假设堆栈不为空。这是性能关键代码的有用方法:

template <class T>
T Stack<T>::pop(void) {
    asssert(size > 0);  // not necessary, but it's good practice to assert preconditions
    size--;
    return items[size];
}

上述两种方法假设在空堆栈上调用pop() 是一个错误,即它不应该发生。如果您希望这是一个具有明确定义结果的有效操作,您还有其他一些选择。

返回一个表示成功的标志:

template <class T>
std::pair<T, bool> Stack<T>::pop(void) {
    if (size != 0) {
        size--;
        return std::make_pair(items[size], true);
    } else {
        return std::make_pair(T(), false);  // requires T to be default-constructible
    }
}

返回一个boost::optional

template <class T>
boost::optional<T> Stack<T>::pop(void) {
    if (size != 0) {
        size--;
        return items[size];
    } else {
        return boost::none;
    }
}

返回一个默认构造的T

template <class T>
T Stack<T>::pop(void) {
    if (size != 0) {
        size--;
        return items[size];
    } else {
        return T();
    }
}

【讨论】:

    【解决方案2】:

    通常在这种情况下会引发异常。

    或者你应该将函数pop的返回类型更改为void

    至于函数peak则可以返回对栈中对象的引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-10
      • 2012-05-24
      • 2016-02-23
      • 2021-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      相关资源
      最近更新 更多