微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么C ++允许实际上不返回值的函数?

如何解决为什么C ++允许实际上不返回值的函数?

在C ++中,允许使用具有非空返回类型而没有return语句的函数。因此,将编译以下代码

std::string give_me_a_string()
{
}

但是,在C#中,不允许使用这种方法。因此,以下代码将无法编译:

public string GiveMeAString()
{
}

为什么会这样?这两种语言的设计原理是什么?

解决方法

C ++要求“行为良好”的代码才能以定义的方式执行,但是该语言并不比程序员更聪明–当出现可能导致不确定行为的情况时,编译器可以自由地假设这种情况实际上不可能在运行时发生,即使无法通过静态分析来证明也是如此。

从函数末尾流出就等于没有值的返回;这会导致返回值函数的行为不确定。

调用此类函数是合法行为;仅在没有提供值的情况下从其末端流出是不确定的。我会说允许这样做有正当(主要是传统)原因,例如,您可能正在调用一个总是抛出异常或执行longjmp的函数(或有条件地这样做,但您知道它总是在这种情况下发生位置,[[noreturn]]仅在C ++ 11中出现。

这是一把双刃剑,因为虽然不必在无法确定的情况下提供值可能会有利于进一步优化代码,但您也可能会错误地忽略它,类似于从未初始化的变量。过去有很多这样的错误,所以这就是现代编译器向您发出警告的原因,并且有时还会插入防护措施,以使其在运行时易于管理。

作为说明,过度优化的编译器可以假设一个永远不会产生其返回值的函数实际上永远不会返回,并且可以进行这种推理直到创建一个空的main方法而不是您的方法。代码。


另一方面,C#具有不同的设计原理。它应被编译为中间代码,而不是本机代码,因此其可定义性规则必须符合中间代码的规则。而且CIL必须是可验证的才能在某些地方执行,因此必须事先检测到从函数末尾流出的情况。

C#的另一原则是在常见情况下不允许未定义的行为。由于它还比C ++还年轻,因此它的优点是假定计算机的效率足以支持比C ++初期情况更强大的静态分析。编译器可以承受这种情况,并且由于CIL必须是可验证的,因此只有两个操作是可行的:静默发出引发异常的代码(某种assert false),或完全禁止这种行为。由于C#还具有从C ++的课程中学习的优势,因此开发人员选择了后者。

这仍然有其缺点–使得辅助方法永不返回,并且仍然无法用语言静态表示此方法,因此调用此类方法后必须使用类似return default;的方法,可能会使阅读代码的人感到困惑。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。