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

时间:2011-12-29 10:15:26

标签: c++ static g++ c++11

这是我能想出的最简单的例子,可以重现问题。

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是普通类而不是模板,则它有效。另外,我认为它与lambdas无关,因为即使我用本地类替换lambda,我也会收到错误。

2 个答案:

答案 0 :(得分:10)

g ++接受以下内容,但VC ++不接受:

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

此处正在捕获z,因此g ++不会抱怨未定义的引用。但是:

  

<强> 5.1.2 / 10:

     

使用通常的非限定名称查找规则(3.4.1)查找捕获列表中的标识符;每个这样的查找都应该找到   在到达时声明自动存储持续时间的变量   本地lambda表达式的范围。

z 自动存储空间。因此无法捕获z。因此,g ++行为是不正确的,VC ++是正确的。

在您的代码中,VC ++接受而g ++不接受:

[]{ z = 1; }();
VC ++将

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

<强> TL;博士 这可能是g ++中的一个错误

修改 It is indeed a bug并在4.7中修复。

答案 1 :(得分:-1)

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

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

维基百科有更多信息here