简体   繁体   English

为什么这个“未定义的外部变量”不会导致C ++ 17中的链接器错误?

[英]Why doesn't this “undefined extern variable” result in a linker error in C++17?

I have compiled and ran the following program in a C++17 compiler (Coliru). 我已经在C ++ 17编译器(Coliru)中编译并运行了以下程序。 In the program, I declared an extern variable, but did not define it. 在程序中,我声明了一个extern变量,但没有定义它。 However, the compiler doesn't give a linker error . 但是,编译器不会给出链接器错误

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

Why doesn't the compiler give a linker error? 为什么编译器没有给出链接器错误?

Because the variable isn't odr-used. 因为变量不是使用odr。 You have a constexpr if there that always discards the branch that could use it. 你有一个constexpr if那里总是丢弃可以使用它的分支。

One of the points of constexpr if is that the discarded branch need not even compile, only be well-formed. constexpr if一个要点是丢弃的分支甚至不需要编译,只有格式良好。 That's how we can place calls to non-existing member functions in a discarded branch. 这就是我们如何在一个被丢弃的分支中调用不存在的成员函数。

In your case the variable is used in discarded statements only. 在您的情况下,变量仅用于废弃的语句中。 However, even if we ignore that fact, C++ language specification still explicitly states that no diagnostic is required for missing definitions 但是,即使我们忽略了这一事实,C ++语言规范仍然明确指出缺少定义不需要诊断

3.2 One-definition rule 3.2单一定义规则

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); 4每个程序应包含在废弃陈述之外的该程序中使用的每个非内联函数或变量的一个定义(6.4.1); no diagnostic required . 无需诊断

The language specification understands that an optimizing compiler might be smart enough to eliminate all odr-uses of a variable. 语言规范理解优化编译器可能足够智能以消除变量的所有odr使用。 In that case it would be excessive and unnecessary to require the implementation to detect and report the potential ODR violations. 在这种情况下,要求实施检测和报告潜在的ODR违规是过分和不必要的。

Because the compiler produces compiler errors, the linker would yield linker errors ... 因为编译器会产生编译器错误, 链接器会产生链接器错误......

No, seriously: 不,认真:

if constexpr (true)

is always true, so the compiler ignores the rest of the if-clause because it is never reached. 始终为true,因此编译器会忽略if子句的其余部分,因为它永远不会到达。 So i is never used actually. 所以i从未使用过。

This has alrady been answered, but if you are interested, cppreference.com has exactly this example for constexpr if : 这已经得到了回答,但是如果你有兴趣, cppreference.com就是constexpr的这个例子, 如果

Constexpr If Constexpr如果

The statement that begins with if constexpr is known as the constexpr if statement . if constexpr开头的语句称为constexpr if语句

In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool. 在constexpr if语句中, condition的值必须是bool类型的上下文转换常量表达式 If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded. 如果值为true,则抛弃statement-false (如果存在),否则将丢弃statement-true
[...] [...]
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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM