为什么这个“未定义的外部variables”导致C ++ 17中的链接器错误?
我已经编译并在C ++ 17编译器(Coliru)中运行以下程序。 在程序中,我宣布了一个extern
variables,但没有定义它。 但是,编译器不会给出链接器错误 。
#include <iostream> extern int i; // Only declaration int func() { if constexpr (true) return 0; else if (i) return i; else return -1; } int main() { int ret = func(); std::cout<<"Ret : "<<ret<<std::endl; }
为什么编译器不提供链接器错误?
因为这个variables没有被使用。 你有一个constexpr if
总是丢弃可以使用它的分支。
其中constexpr if
一个要点就是被丢弃的分支甚至不需要编译,只有格式良好。 这就是我们如何将调用放在不存在的成员函数放在一个废弃的分支。
在你的情况下,variables只用于放弃语句。 但是,即使我们忽略了这一事实,C ++语言规范仍然明确规定缺less定义不需要诊断
3.2一个定义的规则
(4)每个程序只能包含在该程序中被丢弃的语句(6.4.1)以外的每个非内联函数或variables的定义。 不需要诊断 。
语言规范理解优化编译器可能足够聪明,以消除variables的所有odr用法。 在这种情况下,要求实施检测和报告潜在的ODR违规行为将是过度的,没有必要的。
由于编译器生成编译器错误, 链接器会产生链接器错误…
不,严重:
if constexpr (true)
总是如此,所以编译器会忽略if子句的其余部分,因为它永远不会到达。 所以i
从来没有用过。
这已经得到了回答,但是如果你有兴趣, cppreference.com正好具有这个例子, 如果 :
Constexpr如果
if constexpr
开头的语句被称为constexpr if语句 。在constexpr if语句中, condition的值必须是一个上下文转换的booltypes的常量expression式 。 如果该值为true,那么将抛弃statement-false (如果存在),否则将丢弃statement-true 。
[…]
丢弃的语句可以使用一个未定义的variables:
extern int x; // no definition of x required int f() { if constexpr (true) return 0; else if (x) return x; else return -x; }