对静态局部变量的未定义引用

Undefined reference to a static local variable

本文关键字:未定义 引用 局部变量 静态      更新时间:2023-10-16

这是我能想到的重现这个问题的最简单的例子。

template<class T>
struct X
{
    static void foo()
    {
        static int z = 0;
        []{ z = 1; }();
    }
};
int main()
{
    X<int>::foo();
    return 0;
}

我已经在MinGW 4.6和4.7,以及Ubuntu中的g++ 4.6中尝试过了,它们都给了我链接错误"对' z'的未定义引用"。这让我怀疑这是否合法。VC10没有问题。

如果X是一个普通类而不是模板,它就可以工作。此外,我不认为这与lambda有关,因为即使我用本地类替换lambda,我也会得到错误。

c++可以接受以下内容,但vc++不接受:

[&z]{ z = 1; }();

这里捕获z,因此g++不会抱怨未定义的引用。然而:

5.1.2/10:

捕获列表中的标识符使用非限定名查找的常规规则进行查找(3.4.1);每个这样的查找将找到在到达时声明具有自动存储持续时间的变量局部lambda表达式的作用域。

z而非自动存储。因此,z不能被捕获。因此,c++的行为是不正确的,vc++是正确的。

在你的代码中,vc++接受而g++不接受:

[]{ z = 1; }();

z被vc++作为静态存储访问,这在lambda体中是允许的。显然,g++没有将名称z解析为上面声明的静态变量,因此抛出未定义的引用,而它本不应该这样做。

tl;博士这可能是g++

中的一个bug编辑:

我不明白为什么它适用于普通类而不是模板。但是,如果您通过引用捕获局部变量z,则可以使示例工作:

static void foo()
{
    static int z = 0;
    [&z]{ z = 1; }(); // Note: [&z]
}

维基百科有更多信息。