[c++11]静态成员在类中的初始化总结(static,static const,static constexpr)

本文详细解析C++11中静态成员的初始化规则,包括哪些类型可以在类内初始化,哪些必须在类外定义。重点讨论了static const int、static constexpr的使用,并通过实例说明了类内定义的static成员在外必须再次定义的原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[c++11]静态成员在类中的初始化总结(static,static const,static constexpr)

阅读《c++ primer (5th)》的7.6章(270页)关于静态成员的类内初始化,看的我云里雾里,感觉是中文写的有问题,翻了英文版后,个人认为是原版作者在这块没有阐述清楚。

一般的,

  • 类的静态成员必须放在类外定义(也就是说类的静态成员不应该放在类内初始化)
  • 对此有两个特例:
    • 允许static const int 类型有类内初始值(允许但不强求)
    • static constexpr类型必须有类内初始值

与此同时,凡是在类内定义的static数据成员必须在类外再次定义一次(不需要带初始值),否则无法被其他函数引用或者取地址。

struct A{
	static const int i0;//正确
	static const int i1=2;//正确

	static const std::string str2;//正确
	static const std::string str3="你太baby辣";//error:只允许static const int有类内初始值
	static const float f0=3f;//error:只允许static const int 类型在类内定义
	
	static constexpr int i2=4;//正确,static constexpr必须是类内初始值
	static constexpr int i3;//error
	static constexpr std::string str0;//error:没有类内初始值
	static constexpr std::string str1="c++是男人的浪漫";//正确
};

//类内定义的static数据成员必须在类外再次定义一次
const int A::i0=1;
const int A::i1;

const std::string A::str2="000";
const std::string A::str3;
const float A::f0;

constexpr int A::i2;
constexpr int A::i3=5;
constexpr std::string A::str0="456";
constexpr std::string A::str1;

以上

### 关于 C++ 中 `static const float` 成员变量无法在初始化的原因 #### 编译器支持与标准规定 C++11 引入了新的特性,允许某些型的静态成员变量在内部进行初始化。然而,对于 `static const float` 这种情况,其限制主要来源于编译器实现细节以及语言设计的选择。具体来说: - **整数型的支持** 对于 `static const int` 或者更广泛的整型常量,在 C++98 和后续版本中被特别处理,因为它们可以直接嵌入到程序的字节码中作为立即数使用[^1]。 - **浮点数的不同性质** 浮点数值由于涉及精度问题和可能存在的平台差异(比如 IEEE754 表示法),并不总是能够简单地由编译期完全解析并安全存储为立即数。因此,尽管逻辑上看起来合理,但实际上标准化过程中并未扩展此行为至浮点数型[^2]。 #### 存储位置的影响 另一个重要因素涉及到内存布局与生命周期管理: - 当声明了一个 `static const float` 变量时,它实际上需要一块实际分配的空间来保存该值(即使它是只读),而不仅仅只是一个符号替代品。 - 如果允许直接在体内完成这样的操作,则可能导致跨文件链接阶段出现问题或者增加额外复杂度给开发者去理解何时何地应该真正定义这些实体[^3]。 #### 构造过程中的约束条件 最后一点值得注意的是,即便是在现代 C++ 版本里(`C++17`, `C++20`) ,如果某个数据项标记为了 `constexpr`(即运行时常表达式), 它也必须满足特定的要求才能成为真正的编译时期计算结果;而对于普通的 `const` 声明而言 (不带 `constexpr` 属性卡顿),则仍然遵循传统规则——即需显式提供外部定义以便正确初始化[^4]. ```cpp class Example { public: static constexpr int valueA = 42; // 合法, 因为此处可视为编译期间确定. static const float valueB = 3.14f; // 错误! 不符合现行规范. private: struct Helper {}; }; // 正确做法 const float Example::valueB = 3.14f; ``` 综上所述,出于兼容性和一致性的考虑,“不允许 `static const float` 在体内的初始化”的决策保持了一定程度上的合理性,并且有助于减少潜在错误的发生几率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值