C++11新特性:强类型枚举/编译期断言/元组
本期我们简单介绍一下C++11中一些常见的简单的特性:强类型枚举/编译期断言/元组。
相关代码上传至作者个人gitee:楼田莉子/CPP代码学习
目录
强类型枚举
参数解释
1. enum class
2. EnumName
3. [: UnderlyingType](可选)
4. 枚举值列表
强类型枚举的优势
编译期断言
static_assert 和 assert 对比表
元组
构造
关系运算符
交换
非成员函数
成员函数
获取元素
解包元组
强类型枚举
C++11 引⼊了强类型枚举(也称为枚举类enum class),解决了传统 C++ 枚举(enum)的多个缺点,提供了更好的类型安全性和封装性。
传统 C++ 枚举存在以下主要问题:
1. 隐式转换为整型:枚举值会⾃动转换为整数,可能导致意外⾏为
2. 污染外围作⽤域:枚举值会泄漏到包含它的作⽤域中
3. ⽆法指定底层类型:不能明确控制枚举使⽤的存储⼤⼩
强类型枚举语法:
• enum class 或 enum struct (两者等价)
• 可选的底层类型( : UnderlyingType )
• 枚举值必须通过枚举名作⽤域访问
语法格式如下:
enum class EnumName [: UnderlyingType] {
enumerator1,
enumerator2,
// ...
}
参数解释
1. enum class
-
作用:声明这是一个强类型枚举(scoped enumeration)
-
特点:与传统的C风格枚举不同,强类型枚举的枚举值不会泄漏到外围作用域
2. EnumName
-
作用:枚举类型的名称
-
用法:用于声明该类型的变量
-
示例:
enum class Color { Red, Green, Blue };
Color myColor = Color::Red; // 必须使用作用域解析
3. [: UnderlyingType](可选)
-
作用:指定枚举的底层数据类型
-
默认值:如果不指定,默认为
int -
可用的类型:任何整数类型(如
char,short,int,unsigned int等) -
示例:
enum class SmallEnum : char { A, B, C }; // 底层类型为char
enum class ByteEnum : uint8_t { ON, OFF }; // 底层类型为uint8_t
4. 枚举值列表
-
作用:定义枚举的具名常量
-
语法:
enumerator1, enumerator2, ... -
赋值:可以显式赋值或使用默认值(从0开始递增)
-
示例:
enum class Status {Success = 0,Error = 1,Processing = 2
};enum class Priority {Low, // 0Medium, // 1 High // 2
};
强类型枚举的优势
-
作用域安全:枚举值必须通过类型名访问
-
类型安全:不会隐式转换为整数
-
前向声明:可以前向声明枚举
-
明确底层类型:可以控制枚举的内存占用
注意!
// 使⽤enum是不可以这样定义的,enum值是暴露到全局的,Red存在冲突
enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };
// 指定底层类型
enum class SmallEnum : uint8_t { Value1, Value2 }; // 8位存储
enum class BigEnum : uint32_t { Value1, Value2 }; // 32位存储
测试代码:
#include <iostream>
using namespace std;// 使⽤enum是不可以这样定义的,enum值是暴露到全局的,Red存在冲突
enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };
int main()
{Color c1 = Color::Red; // 正确//Color c2 = Red; // 错误, enum是可以的//int i = Color::Red; // 错误:不能隐式转换,enum是可以的int j = static_cast<int>(Color::Red); // 正确:显式转换// C++20⽀持using enum Color; // 引⼊Color枚举值到当前作⽤域Color c = Red; // 现在可以直接使⽤return 0;
}
编译期断言
static_assert 是C++11引⼊的编译时断⾔机制,它允许开发者在编译期间检查条件是否满⾜,如果条件不满⾜,则会导致编译错误。 static_assert 是C++元编程和模板编程中⾮常有⽤的⼯具,
它可以帮助开发者在编译期捕获错误,提⾼代码的健壮性
// 常量表达式:在编译时可求值的表达式,必须能转换为bool类型
// 错误消息:当断⾔失败时显⽰的字符串字⾯量(C++17起可以省略)
static_assert(常量表达式, 错误消息);
常见使用场景:
// 1、类型检查
template<typename T>
void process(T value) {
static_assert(std::is_integral<T>::value, "T must be an integral type");
// 函数实现...
} /
/ 2、编译时常量验证
constexpr int buffer_size = 1024;
static_assert(buffer_size > 0, "Buffer size must be positive");
static_assert(buffer_size % 4 == 0, "Buffer size must be divisible by 4");'
// 3、平台或架构检查
static_assert(sizeof(void*) == 8, "This code requires 64-bit platform");
// 4、类型⼤⼩验证
static_assert(sizeof(int) == 4, "int must be 4 bytes");
static_assert 和 assert 对比表
| 方面 | static_assert | assert |
|---|---|---|
| 检查时机 | 编译时 | 运行时 |
| 错误类型 | 编译错误 | 运行时错误/断言失败 |
| 性能影响 | 无运行时开销 | 有运行时开销(调试版本) |
| 依赖头文件 | <type_traits>(C++11起内置) | <cassert> |
| 语法 | static_assert(constexpr_bool, "message") | assert(expression) |
| 条件类型 | 常量表达式 | 运行时表达式 |
| 消息 | 必需提供错误消息 | 可选消息(通过表达式组合) |
| 用途 | 编译期条件检查、类型特性验证 | 调试期逻辑验证、前置/后置条件检查 |
| 发布版本 | 始终保留 | 通常被NDEBUG宏禁用 |
| C++标准 | C++11引入 | C标准库,C++继承 |
| 典型用例 | 类型大小验证、概念检查 | 指针非空检查、边界验证 |
元组
std::tuple 是 C++11 引⼊的⼀个模板类,它允许将多个不同类型的值组合成⼀个单⼀的对象。类似于结构体,但不需要预先定义类型名称。
tuple(元组)是⼀个固定⼤⼩的异构值集合,可以包含不同类型的元素。它是 std::pair 的泛化版本, pair 只能保存两个元素,⽽ tuple 可以保存任意数量的元素。
官方文档:元组 - C++ 参考
构造
// 创建⼀个包含3个元素的tuple: int, double, string
std::tuple<int, double, std::string> t1(10, 3.14, "hello");
// 使⽤make_tuple⾃动推导类型
auto t2 = std::make_tuple(20, 2.718, "world");
// C++17起可以使⽤类模板参数推导
std::tuple t3(30, 1.618, "cpp"); // ⾃动推导为tuple<int, double, const char* >
//如果要推导为string类型可以用
std::tuple t3(30, 1.618, std::string("cpp"));
关系运算符

交换
非成员函数

成员函数

获取元素

测试代码:
#include <iostream>
#include <tuple>
using namespace std;
int main()
{std::tuple<int, double, std::string> t1(10, 3.14, "hello");// 通过索引访问std::cout << std::get<0>(t1) << std::endl; // 输出10std::cout << std::get<1>(t1) << std::endl; // 输出3.14std::cout << std::get<2>(t1) << std::endl << std::endl; // 输出"hello"// 修改std::get<0>(t1) = 100; // 修改第⼀个元素// C++14起可以通过类型访问(类型必须唯⼀)std::cout << std::get<int>(t1) << std::endl; // 输出100std::cout << std::get<double>(t1) << std::endl; // 输出3.14return 0;
}
解包元组
int x;double y;
std::string z;
// 使⽤std::tie解包
std::tie(x, y, z) = t1;
// C++17结构化绑定
auto [a, b, c] = t1;
本期内容就到这里了,喜欢请点个赞谢谢
封面图自取:

