为什么在C++类中只能初始化整数或枚举类型

Why only integral or enum type can be initialised in a C++ class?

本文关键字:整数 初始化 枚举 类型 C++ 为什么      更新时间:2023-10-16

我不明白为什么C++只允许在类声明中定义整型和枚举(枚举也是整型类型)。而所有其他类型,包括浮点类型(即双精度和浮点),必须在类声明之外定义。显然,这一定是造成这种情况的原因,但我无法弄清楚。

代码示例:

#include <iostream>
using namespace std;
struct Node {
  static const int c = 0;  // Legal Definition 
  static const long l = 0l; // Legal Definition 
  static const short s = 0; // Legal Definition 
  static const float f = 0.0f; // Illegal definition 
  static const string S = "Test"; // Illegal definition 
  static const string JOB_TYPE; // Legal declaration
  static const float f; // Legal declaration 
  static const double d; // Legal declaration 
};
const string Node::JOB_TYPE = "Test"; // correct definition
const float Node::f = 0.0f;  // correct definition 
const double Node::d = 0.0;  // correct definition 
int main() {
  cout << Node::c << endl;
  cout << Node::c << endl;
  cout << Node::JOB_TYPE << endl;
  cout << Node::f << endl;
}

这里的关键原因是整型类型(和enum,因为它们在编译器内部成为某种整数)可以简单地替换并直接用作常量。

换句话说,struct S { static const int x = 42;},如果编译器看到S::x,它可以立即用生成的代码中的常量42替换它。这同样不适用于float,当然也不适用于依赖于构造函数的类型,例如std::string - 编译器无法在不调用new(或std::string::allocator)的情况下为std::string分配内存。因此,对于必须"构造"和/或具有更复杂的使用标准的常量(想想没有对浮点的硬件支持的处理器 - 加载和存储浮点值的函数调用等),语言不能规定应该允许它这样做。

如果将struct Node声明包含在 static const std::string S = "test"; 中,编译器应将Node::S存储在多少个位置?当它最终将您的三个翻译单元链接到一个程序中时,它应该使用哪一个 - 或者它应该使用不同的程序?如果您const_cast Node::S并对其进行修改,会发生什么?后者假设你有一个不会导致崩溃的环境,这是完全合理的,虽然这是未定义的行为,但我不确定编译器是否应该让它像在每个翻译单元中使用不同的值一样奇怪在这种情况下......

编辑:正如评论中提到的,C++11确实允许以类似的方式使用更多类型,因此随着编译器和硬件技术的改进,限制正在放宽。我怀疑你永远无法static const std::map<X, Y> a = { ... } tho,因为这是一个相当复杂的数据类型来构建......

初始化std::string需要在运行时执行一些代码。

使用字符串文本初始化指针需要将字符串放在内存中的某个位置,也在运行时中。