为什么编译这个 C++ 代码片段(非 void 函数不返回值)

2021-12-23 00:00:00 methods c++ c++11 visual-studio-2012

今天早上我在我的一个图书馆中发现了这个:

I found this in one of my libraries this morning:

static tvec4 Min(const tvec4& a, const tvec4& b, tvec4& out)
{
    tvec3::Min(a,b,out);
    out.w = min(a.w,b.w);
}

我预计会出现编译器错误,因为此方法不返回任何内容,并且返回类型不是 void.

I'd expect a compiler error because this method doesn't return anything, and the return type is not void.

想到的只有两件事

  • 在调用此方法的唯一地方,未使用或存储返回值.(这个方法应该是 void - tvec4 返回类型是一个复制粘贴错误)

  • In the only place where this method is called, the return value isn't being used or stored. (This method was supposed to be void - the tvec4 return type is a copy-and-paste error)

正在创建一个默认构造的 tvec4,这看起来有点不像,哦,C++ 中的其他一切.

a default constructed tvec4 is being created, which seems a bit unlike, oh, everything else in C++.

我还没有找到解决这个问题的 C++ 规范部分.参考文献 (ha) 表示赞赏.

I haven't found the part of the C++ spec that addresses this. References (ha) are appreciated.

更新

在某些情况下,这会在 VS2012 中产生错误.我没有细化细节,但还是很有趣.

In some circumstances, this generates an error in VS2012. I haven't narrowed down specifics, but it's interesting, nonetheless.

推荐答案

This is 未定义行为来自 C++11 标准草案部分6.6.3 返回语句 段落 2 说:

This is undefined behavior from the C++11 draft standard section 6.6.3 The return statement paragraph 2 which says:

[...] 从函数末尾流出相当于没有值的返回;这会导致值返回函数中的未定义行为.[...]

[...] Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function. [...]

这意味着编译器通常没有义务提供错误或警告,因为在所有情况下都很难诊断.我们可以从1.3.24部分的标准草案中未定义行为的定义中看出这一点:

This means that the compiler is not obligated provide an error nor a warning usually because it can be difficult to diagnose in all cases. We can see this from the definition of undefined behavior in the draft standard in section 1.3.24 which says:

[...] 允许的未定义行为的范围从完全忽略情况并产生不可预测的结果,在翻译或程序执行期间以环境特征的记录方式行事(有或没有发布诊断消息),到终止翻译或执行(带有诊断消息).[...]

[...]Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).[...]

虽然在这种情况下我们可以使用 -Wall 标志让 gccclang 生成警告,这给了我一个警告类似这样:

Although in this case we can get both gcc and clang to generate a wanring using the -Wall flag, which gives me a warning similar to this:

警告:控制到达非空函数结束[-Wreturn-type]

warning: control reaches end of non-void function [-Wreturn-type]

我们可以使用 -Werror=return-type 标志将此特定警告转换为错误.我也喜欢将 -Wextra -Wconversion -pedantic 用于我自己的个人项目.

We can turn this particular warning into an error using the -Werror=return-type flag. I also like to use -Wextra -Wconversion -pedantic for my own personal projects.

正如 ComicSansMS 在 Visual Studio 中提到的,此代码将生成 C4716 默认情况下这是一个错误,我看到的消息是:

As ComicSansMS mentions in Visual Studio this code would generate C4716 which is an error by default, the message I see is:

错误 C4716:'Min':必须返回一个值

error C4716: 'Min' : must return a value

并且在并非所有代码路径都会返回值的情况下,它会生成 C4715,这是一个警告.

and in the case where not all code paths would return a value then it would generate C4715, which is a warning.

相关文章