为什么这个 "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.com 有 constexpr 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;
}
我已经在 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.com 有 constexpr 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;
}