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

Weird uninitialized const member behavior

考虑这个代码片段:

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 的行为似乎就是这样。

如果您的 class/struct 中有 const 数据成员,则编译器不会为此生成默认构造函数。您必须显式定义它并初始化该 const 成员(而不是分配它)。

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

我认为它应该始终产生错误。 Clang 这样做了。 C++ 标准在 §12.1.4 的条款 (4.3) 中说 当

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

— any non-variant non-static data member of const-qualified type (or array thereof) with no brace-or equal-initializer does not have a user-provided default constructor,

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

也许向 GCC 报告错误?

看起来 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 文档中找到解释这一点的参考资料...)