奇怪的未初始化的const成员行为

时间:2015-01-02 13:51:31

标签: c++ c++11 gcc

请考虑以下代码段:

struct Foo {

};

template<typename T>
struct Bar {
    const T foo;
};

int main() {
    Bar<Foo> test;
}

我用g ++ - 4.9.2用[-std = c ++ 11 -O0 -g3 -pedantic -Wall -Wextra -Wconversion]编译它并获得error: uninitialized const member in ‘struct Bar<Foo>’。这很明显。

但是尝试添加std :: string作为Foo成员和程序编译!

#include <string>
struct Foo {
    std::string test;
};
// (...)

发生了什么?将测试类型替换为double会导致程序无法再次编译。什么字符串成员在类中更改?

Link to online compiler with this snippet.

从版本4.6开始,gcc似乎就像那样。

3 个答案:

答案 0 :(得分:17)

我认为应始终如一地产生错误。 Clang这样做了。 C ++标准在§12.1.4的第(4.3)节中说过

时隐式删除​​默认构造函数
  

- const限定类型的任何非变量非静态数据成员(或   没有支撑或等初始化器的数组)没有   用户提供的默认构造函数,

由于Foo没有用户提供的默认构造函数,Bar应该有一个隐式删除的默认构造函数,因此在main中实例化Bar<Foo> test会产生错误。

也许向GCC报告错误?

答案 1 :(得分:4)

如果您的类/结构中有const数据成员,则编译器不会为此生成默认构造函数。您必须明确定义它并初始化const成员(不分配它)。

两种情况都应该是错误的。

答案 2 :(得分:2)

看起来g ++会自动生成默认构造函数,即使const成员应该在构造时初始化,因为它知道字符串有一个默认构造函数,将其初始化为空字符串。事实上,所有事情都发生在源头:

struct Foo {
    std::string test;
    Foo():test() {;}
};

template<typename T>
struct Bar {
    const T foo;
    Bar(): foo() {;}
};

int main() {
    Bar<Foo> test;
}

用clang和MSVC编译好。

(但我必须承认,我仍然没有找到gcc doc中的参考资料来解释......)