为什么这个 "undefined extern variable" 不会导致 C++17 中的链接器错误?

Why doesn't this "undefined extern variable" result in a linker error in C++17?

我已经在 C++17 编译器 (Coliru) 中编译并 运行 以下程序。在程序中,我声明了一个extern变量,但是没有定义它。但是,编译器不会给出 链接器错误 .

#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;
}

为什么编译器不给出链接器错误?

因为该变量未被 ODR 使用。你有一个 constexpr if 总是丢弃可以使用它的分支。

constexpr if的要点之一是丢弃的分支甚至不需要编译,只需要格式正确即可。这就是我们如何在废弃的分支中调用不存在的成员函数。

因为编译器会产生编译器错误,链接器会产生链接器错误...

不,认真的:

if constexpr (true)

始终为真,因此编译器会忽略 if 子句的其余部分,因为它永远不会到达。所以 i 实际上从未被使用过。

在您的例子中,该变量仅用于丢弃的语句。然而,即使我们忽略这个事实,C++ 语言规范仍然明确指出 不需要诊断 缺少定义

3.2 One-definition rule

4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement (6.4.1); no diagnostic required.

语言规范理解优化编译器可能足够聪明,可以消除变量的所有 odr-uses。在这种情况下,要求实施检测和报告潜在的 ODR 违规行为将是过度且不必要的。

这已经得到解答,但如果您有兴趣,cppreference.comconstexpr if:

的示例

Constexpr If

The statement that begins with if constexpr is known as the constexpr if statement.

In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool. If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.
[...]
The discarded statement can odr-use a variable that is not defined:

extern int x; // no definition of x required
int f() {
if constexpr (true)
    return 0;
else if (x)
    return x;
else
    return -x;
}