请考虑以下代码段:
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似乎就像那样。
答案 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中的参考资料来解释......)