如果有[[noreturn]]
(C2X,n3301),那么为什么没有[[always_return]]
?
的语义[[always_return]]
可能如下:
使用属性声明的函数
[[always_return]]
应始终返回其调用者。
其基本原理[[always_return]]
是提示编译器进行优化。
示例(取自N3128):
extern void g(int x);
int f(int a, int b)
{
g(b ? 42 : 43);
return a / b;
}
编译器可以自由地(乐观地)假设 UB 不会发生。
但是,UB 的任何(危险)后果只有当 UB 发生时(即在抽象机器级别的执行中出现)才会发生。
在此示例中g
可能会终止程序(即不返回)。因此,据我了解,编译器可能不会折叠b ? 42 : 43
到 42,因为在抽象机器级别a / b
可能不会执行,因此编译器可能不会b
传播/使用非零的假设。
但是,如果g
用声明[[always_return]]
,那么据我所知,编译器可能会折叠b ? 42 : 43
到 42,因为在抽象机器级别a / b
总是执行,因此编译器可能会b
传播/使用非零的假设。
PS 同样的问题也存在[[may_return]]
。
UPD。为了折叠b ? 42 : 43
到 42,g
不仅需要始终返回,还需要没有可观察的行为 (OB)。这是因为在 C 中,OB 必须在 UB 之前发生。因此,可能需要更多属性:[[observable]]
,[[noobservable]]
。并且g
可以声明为:
extern [[always_return]] [[noobservable]] void g(int x);
归根结底,因为委员会认为添加这样的属性没有(足够的)价值。我倾向于猜测他们没有看到价值,因为甚至没有提出过这个建议,但如果提出了,那么它被拒绝了。当然,添加的提议
[[noreturn]]
并没有考虑到[[always_return]]
。为什么会这样呢?用户函数无法确保它总是返回。在执行函数期间,程序总是有可能被终止,或者通过调试器阻止其返回,或者函数程序员无法控制的任何其他事情恰好阻止函数返回。
这有什么好处呢?在缺乏任何属性和/或特定函数的特殊知识的情况下,C 实现必须假定函数调用将返回。但即使承诺
[[always_return]]
实际上可以可靠地保持,该信息对实现也没有用。这就像我断言明天太阳会升起一样。即使假设你基于这些理由对我有绝对的信心,你会做任何不同的事情吗?不会,因为在任何程度上,只要它有区别,你就已经把它当作一个工作假设了。[[noreturn]]
是不同的。与设计上不会返回的未标记函数相比,它提供了性能增强和改进的诊断。此外,
[[noreturn]]
属性是自 C11 以来就存在于 C 中的函数说明符的替代方案_Noreturn
,因此它实际上并不是一个新功能。切换到属性而不是说明符支持与 C++ 的协调。没有类似于您假设的函数说明符[[always_return]]
。