news 2026/9/2 23:21:22

【Effective Modern C++】第三章 转向现代C++:10. 优先选用限域枚举,而非不限域枚举

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Effective Modern C++】第三章 转向现代C++:10. 优先选用限域枚举,而非不限域枚举

使用限域enum来减少命名空间污染

通用规则:如果在一对大括号里声明一个名字,则该名字的可见性限定在括号括起来的作用域内。

但这个规则不适用于 C++98 风格的枚举类型中定义的枚举变量:枚举变量的属于包含着这个枚举类型的作用域,此作用域内不能有其他实体取相同的名字。

enum Color { black, white, red }; //black, white, red在Color所在的作用域 auto white = false; //错误! white早已在这个作用域中声明

枚举量的名字泄露到枚举类型所在作用域的现象被称为:不限范围的枚举类型(未限域enum)。

在 C++11 中,限定作用域的枚举类型(枚举类 / 限域enum)不会以这样的方式泄露名字:

enum class Color { black, white, red }; //black, white, red限制在Color域内 auto white = false; //没问题,域内没有其他“white” Color c = white; //错误,域中没有枚举名叫white Color c = Color::white; //没问题 auto c = Color::white; //也没问题(也符合5的建议)

限域枚举的枚举量是强类型的

强类型:语言会对类型兼容性做严格检查,禁止隐式的、不安全的类型转换,每个值都有明确且固定的类型,类型错误会被尽可能早地捕获(编译器 / 运行期)。

不限域枚举类型的枚举量可以隐式转换为整数类型(并能够从此处进一步转换到浮点类型),导致语义扭曲的代码合法:

enum Color { black, white, red }; //未限域enum std::vector<std::size_t>primeFactors(std::size_t x); //func返回x的质因子 Color c = red; if (c < 14.5) { // Color与double比较 (!) auto factors = primeFactors(c); // 向std::size_t参数传递Color (!) … }

从限定作用域的枚举类型到任何其他类型都不存在隐式转换路径,类型安全更优:

enum class Color { black, white, red }; //Color现在是限域enum Color c = Color::red; if (c < 14.5) { //错误!不能比较Color和double auto factors = primeFactors(c); //错误!不能向std::size_t参数传Color … } // 仅显式强制转换才允许(可控的类型转换) if (static_cast<double>(c) < 14.5) { auto factors = primeFactors(static_cast<std::size_t>(c)); }

限定作用域的枚举类型可以进行前置声明

前置声明的核心前提是编译器能确定枚举的底层类型(内存大小)

enum Color; // 错误!未限域enum无默认底层类型,编译器无法推断内存大小 enum class Color; // 没问题!限域enum默认底层类型为int,内存大小确定

底层类型与前置声明的完整规则

  1. 所有enum的底层类型是编译器为优化内存选择的整型(需覆盖所有枚举值的最小类型);
  2. 限域enum:默认底层类型为int(也可显式指定),因此总能直接前置声明
enum class Status; // 默认int,合法 enum class Status: std::uint32_t; // 显式指定底层类型,合法
  1. 未限域enum:无默认底层类型,仅显式指定底层类型时才能前置声明
enum Color: std::uint8_t; // 显式指定底层类型,合法
  1. 两者均可在定义时显式指定底层类型:
enum class Status: std::uint32_t { good = 0, failed = 1 }; enum Color: std::uint8_t { black, white, red };

未限域枚举的唯一实用场景:简化std::tuple字段访问

限域enum虽类型安全,但访问std::tuple字段时因无隐式转换,代码冗长;未限域enum可利用 “隐式转换为std::size_t” 简化模板实参传递:

// 定义tuple类型(存储用户名、邮箱、声望值) using UserInfo = std::tuple<std::string, std::string, std::size_t>; // 未限域enum:简洁访问tuple字段(依赖隐式转换为std::size_t) enum UserInfoFields { uiName, uiEmail, uiReputation }; UserInfo uInfo; auto val = std::get<uiEmail>(uInfo); // 直接用枚举成员作为模板实参 // 限域enum:无隐式转换,代码冗长 enum class UserInfoFields { uiName, uiEmail, uiReputation }; auto val = std::get<static_cast<std::size_t>(UserInfoFields::uiEmail)>(uInfo);

限域枚举访问 tuple 的优化方案:toUType constexpr 函数模板

为兼顾限域enum的类型安全与tuple访问的简洁性,可实现编译期生效toUType函数模板(转换枚举值为其底层类型):

C++11 版本:

template<typename E> constexpr typename std::underlying_type<E>::type toUType(E enumerator) noexcept { return static_cast<typename std::underlying_type<E>::type>(enumerator); }

C++14 简化版本(更简洁):

template<typename E> constexpr auto toUType(E enumerator) noexcept { return static_cast<std::underlying_type_t<E>>(enumerator); }

调用方式(兼顾安全与简洁):

auto val = std::get<toUType(UserInfoFields::uiEmail)>(uInfo);

总结

  • C++98风格的枚举类型称为不限范围的枚举类型。
  • 限定作用域的枚举类型仅在枚举类型内可见。它们只能通过cast强制类型转换以转换至其他类型。
  • 限定作用域的枚举类型和不限范围的枚举类型都支持底层类型指定。限域的枚举类型的默认底层类型是int,而不限域的枚举类型没有默认底层类型。
  • 限定作用域的枚举类型总是可以进行前置声明,而不限域的枚举类型却只有在指定了默认底层类型的前提下才可以进行前置声明。

原著在线阅读地址

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 5:26:35

TurboDiffusion儿童绘本动画:故事场景动态化生成案例

TurboDiffusion儿童绘本动画&#xff1a;故事场景动态化生成案例 1. 为什么儿童绘本需要“动起来”&#xff1f; 你有没有试过给孩子讲绘本&#xff0c;讲到“小兔子蹦蹦跳跳穿过森林”时&#xff0c;孩子突然抬头问&#xff1a;“它真的在跳吗&#xff1f;能让我看见它跳的样…

作者头像 李华
网站建设 2026/8/26 4:24:59

如何用GStreamer和AI实现智能视频分析

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个基于GStreamer的视频处理应用&#xff0c;集成AI模型进行实时对象检测。应用应包含以下功能&#xff1a;1. 使用GStreamer捕获视频流&#xff1b;2. 集成YOLOv5或类似模型…

作者头像 李华
网站建设 2026/9/2 12:38:09

1小时用VPS搭建个人博客:从零到上线

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个VPS快速建站工具包&#xff0c;功能包括&#xff1a;1. 一键安装WordPress&#xff1b;2. 自动化域名解析配置&#xff1b;3. Lets Encrypt证书申请&#xff1b;4. 基础SE…

作者头像 李华
网站建设 2026/8/25 23:31:57

Google、OpenAI、Anthropic、xAI、Adept 五大美国主流大模型深度对比

Google、OpenAI、Anthropic、xAI、Adept 五大美国主流大模型深度对比 &#xff08;2026 年 1 月最新&#xff09; 一、写作说明 时间锚点&#xff1a;所有数据与事件均以 2025 年 12 月—2026 年 1 月公开材料为限&#xff0c;不向前“考古”。 对比维度&#xff1a;技术路线、…

作者头像 李华
网站建设 2026/9/2 22:44:56

vssadmin.exe文件丢失找不到免费下载 分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/9/2 23:21:21

再见小鸡模拟器,这2款模拟器才是街机必备!

前段时间分享的《小鸡模拟器》最后一个免费版本&#xff0c;又出了“骚操作”。之前分享的那个免费版本的是V1.8.1&#xff0c;现在强制弹窗必须升级新版本。刚刚我打开了测试了一下&#xff0c;升级到新版本&#xff0c;又无法免费下载。想要白嫖“小鸡模拟器”&#xff1f;现…

作者头像 李华