函数中没有返回语句,返回非void

no return statement in function returning non-void

本文关键字:返回 void 语句 函数      更新时间:2023-10-16

我是编码新手,我得到了此代码的"错误:函数中没有返回语句返回非void":

template <class T>
T Stack<T>::pop()
{
  `myStack.pop_front();
}
template <class T>
T Stack<T>::peek() const
{
  myStack.front();
}

你知道我做错了什么吗?谢谢

函数签名:

template <class T> T Stack<T>::pop()

告诉编译器您的函数将返回type T,但是您的函数实际上不返回任何值,因此编译器警告您可能会犯愚蠢的错误。

因此,在您的情况下,您需要确保声明,
CCD_ 2&CCD_ 3实际上返回一个类型CCD_。

假设您使用的是某个标准库容器,pop_front();只删除容器中的第一个元素,它不会返回任何内容。

您必须添加return关键字:

template <class T>
T Stack<T>::pop()
{
  return myStack.pop_front();
}
template <class T>
T Stack<T>::peek() const
{
  return myStack.front();
}

或类似的东西,这取决于您对stack的实现。

虽然短期解决方案是返回一个值,但最好是pop()的类型为void

template <typename T>
void Stack<T>::pop() {
    ...
}

原因是您不能编写一个异常安全的pop()函数来返回一些东西:

template <typename T>
T Stack<T>::pop() {
    T foo = stor_.top(); // May throw.
    stor_.pop(); // This line shall never throw.
    return foo;  // May throw.
}

第二行(带有pop())不应该抛出某些东西,因为析构函数不应该抛出。因此,假设这一行是另一行并且总是会成功是明智的(除非你弹出一个空容器)。

由于正在复制数据,第一行和第三行可能会抛出。

现在想象一下

    T foo = stor_.top(); // May throw.
    stor_.pop(); // This line shall never throw.

完美地运行:您已经准备好返回一个值,并且您已经成功地更改了持有对象的状态。

但是

    return foo;  // May throw.

bang它抛出一个异常。发生了什么:

  • 函数没有成功,调用方除了一个异常外什么也没得到
  • 不过,该对象的状态已被修改
  • 而且,再也没有人拥有丢失物品的最新副本,其中通常包含老板在发生致命事故前几秒钟打电话给他的关键业务数据

这与Abrahams担保相矛盾:

  • 无抛出保证:操作不会抛出异常。

  • 强有力的保证:操作已成功完成或引发异常,使程序状态与操作开始前完全相同。

  • 基本保证:组件的不变量被保留,并且没有资源泄漏。通常被称为弱保证,因为发生异常后,系统将处于安全但未知的状态。

对于返回值的pop(),您不能保证没有信息丢失。

另请参阅GotW#8和GotW#82

这将起作用:

 template <class T>
    void Stack<T>::pop()
    {
      `myStack.pop_front();
    }
    template <class T>
    void Stack<T>::peek() const
    {
      myStack.front();
    }

或者:

template <class T>
T Stack<T>::pop()
{
  `myStack.pop_front();
  // return something of type T
}
template <class T>
T Stack<T>::peek() const
{
  myStack.front();
  //return something of type T
}

您的签名要求您返回T类型的对象。

template <class T> T Stack<T>::pop()

为了将其分解,位template <class T>意味着对于为T放入的每个类,都将生成代码的另一个副本。例如,如果你做了

堆栈intStack;堆栈双堆栈;

编译器将生成Stack类的两个副本:一个专门用于int,另一个用于double。

所以当你写的时候

template <class T>
T Stack<T>::pop()
{
  myStack.pop_front();
}

您需要返回一个特殊类型的对象。pop_front()只删除第一个元素。你需要访问它删除第一个项目,然后返回它。

这可能不是最好的方法,但为了说明我的观点

template <class T>
T Stack<T>::pop()
{
  T tmp = myStack.front();
  myStack.pop_front();
  return tmp;
}

当您的签名指示函数返回类型T时,您应该将代码更改为以下两个函数的代码。

template <class T>
T Stack<T>::peek()
{
  return myStack.front();
}