【问题标题】:Control reaches end of non-void function控制到达非空函数的结尾
【发布时间】:2012-03-22 09:28:52
【问题描述】:

以下代码sn -p在编译时会产生一些警告信息:

Cluster& Myclass::getCluster(const Point &p)
{
    foreach (Cluster c, *this)
        foreach (Point point, c)
            if (point == p)
                return c;
}

警告是:

  1. 返回对局部变量“c”的引用[默认启用]
  2. 控制到达非空函数的结尾[使用-Wreturn-type时]

我知道如果条件失败,我不会返回值。但是,当我尝试return 0 时,它给了我错误。

我该如何解决这些问题?

【问题讨论】:

  • “当我尝试返回 0 时它给了我错误”是什么意思?您在哪里添加了return 0,错误是什么?

标签: c++ qt return


【解决方案1】:

如果你的函数合法地找不到匹配的Cluster,那么你应该让它返回一个指针:

Cluster* Myclass::getCluster(const Point &p)
{
    foreach (Cluster c, *this)
        foreach (Point point, c)
            if (point == p)
                return &c;
    return 0; // or return nullptr; in C++11
}

但这还不行,因为c 是一个局部变量。所以你把它作为一个参考,像这样:

Cluster* Myclass::getCluster(const Point &p)
{
    foreach (Cluster& c, *this)
        foreach (Point point, c)
            if (point == p)
                return &c;
    return 0; // or "return nullptr;" in C++11
}

【讨论】:

  • 在内部循环中通过引用进行迭代很可能更可取:foreach (const Point& point, c)。 `
  • @TonyK 您能否提供有关返回本地变量作为参考的理论链接?
  • @Dewsworld:我没有返回一个局部变量作为引用——我返回的是c 的地址(因为c 是一个引用,所以它是一个地址已经存在Cluster)。第 6 行中的 & 是“address-of”运算符,第 3 行中的 &c 声明为引用。 C++ 中内置了这种混淆来源。
  • @TonyK 我第一眼就应该明白这一点!没有指出 c 是从非本地的 *this 获取地址。谢谢:)
【解决方案2】:

第一个表示c是一个局部变量。因此,当函数返回时,它将超出范围并死亡。由于您是通过引用返回的,因此调用者会获得一个悬空引用。另一个错误是您在某些情况下无法返回任何东西。返回 0 没有帮助,因为返回类型是对集群的引用。您需要一些机制来确保您将集群引用返回到不会立即死亡的集群。参见例如this question

【讨论】:

    【解决方案3】:

    变量c 一个局部变量,因为它是在getCluster 函数中声明和定义的。通过返回对它的引用,当函数将该引用“点”返回到变量使用的位置时。

    对于另一个警告,如果条件永远不为真,那么函数返回什么?

    【讨论】:

    • 您可能会补充说他的foreach 是一个谎言,因为他实际上不会为每个值执行。这样的谎言往往会让阅读代码的人感到困惑。
    • @James:任何被这样一个简单循环弄糊涂的人首先不应该阅读代码。
    • @TonyK 任何故意编写误导性代码的人都不应该首先编写代码。说您要对序列中的每个元素执行以下操作,然后不执行,这是故意误导。
    • @James:它使用标准的编程结构来执行任务,仅此而已。 “故意误导”是荒谬的。
    【解决方案4】:

    返回的对局部变量“c”的引用[默认启用]

    您不应该返回对局部变量的引用,因为一旦返回函数,该变量就不再存在,因此您引用了不存在的东西。编译器会对此发出警告。

    控制到达非空函数的结尾[-Wreturn-type]

    一旦为函数指定了返回类型,每个控制路径都应该返回该值。如果条件评估为false,那么您的代码将永远不会返回任何内容,因此编译器会抱怨。

    【讨论】:

    • @shobi:如果成功,您应该返回一个指向动态分配内存的指针,如果失败,您将返回 NULL,重要的是,您应该记录这个 api 的行为如果成功,用户应该释放分配的内存。
    • @Als:不,你不应该在这里分配内存。 Cluster 已经存在——你所要做的就是返回它的地址。
    • @TonyK:如果 Cluster 是在本地创建的,我看不出返回其地址将如何解决 OP 问题。
    • @Als:如果您使用引用,则不会在本地创建 Cluster - 请参阅我的答案。
    猜你喜欢
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    • 2013-10-06
    相关资源
    最近更新 更多