奇怪的未初始化的常量成员行为
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;
};
// (...)
怎么回事?将测试的类型替换为双重会导致程序无法再次编译。类中的字符串成员发生了哪些变化?
链接到包含此代码段的联机编译器。
自 4.6 版以来,gcc 的行为似乎就是这样。
我认为它应该始终产生错误。叮当这样做。C++标准在§12.1.4的第(4.3)条中说,默认构造函数在以下情况下被隐式删除
— 任何 const 限定类型的非变量非静态数据成员(或 数组)没有大括号或等号初始值设定项没有 用户提供的默认构造函数,
由于Foo
没有用户提供的默认构造函数,因此Bar
应该有一个隐式删除的默认构造函数,因此在 main 中实例化Bar<Foo> test
应该会产生错误。
也许向 GCC 报告错误?
如果您的类/结构中有const
数据成员,则编译器不会为此生成默认构造函数。您必须显式定义它并初始化该const
成员(而不是分配它)。
在这两种情况下,这都应该是一个错误。
看起来 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 文档中找到解释这一点的参考......
- 私有类型的静态常量成员
- constexpr构造函数需要常量成员函数时出现问题
- 是否可以同时声明一个类成员的常量/非常量?
- 当成员值从指针更改为非指针时,C++常量问题
- 常量公共成员有什么问题?
- Clang 格式 10.0 与 5.0 常量成员函数的格式不同
- C++/QT:使用指向私有成员的常量指针作为只读数据共享
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 为什么"具有常量成员的结构"类型的指针不能指向"具有非常量成员的结构"?
- 初始化依赖于子类的继承类的常量类成员
- 常量成员函数中成员变量的类型
- 如何为非常量和常量重载实现一次成员函数?
- 如何处理运算符=中的常量成员?
- 移动类的成员作为常量引用参数传递
- 为什么我可以改变常量对象中的成员变量,这是返回常量对象函数的结果?
- 常量和引用成员函数限定符
- 返回对常量结构(指针类型)成员的引用:明显的左值到右值转换
- 常量成员和没有setter的私有成员之间有什么区别
- 如何初始化类C++的成员常量向量
- 当我希望调用基类构造函数时,如何在派生类中初始化成员常量引用