在分布式系统、数据库设计、消息队列和微服务架构中生成全局唯一的标识符是一个常见且关键的需求。传统的自增 ID 在分布式环境下存在瓶颈而简单的随机字符串又难以保证唯一性。这时UUIDUniversally Unique Identifier通用唯一识别码 便成为了理想的选择。
Boost C++ 库提供了强大且高效的 boost::uuid 模块它严格遵循 RFC 4122 标准支持多种 UUID 版本1, 3, 4, 5并深度集成于 Boost 生态如 boost::hash、序列化等。
项目配置CMake 示例
cmake_minimum_required(VERSION 3.10) project(boost_uuid_demo) find_package(Boost 1.85.0 REQUIRED COMPONENTS uuid) add_executable(demo main.cpp) target_link_libraries(demo Boost::uuid)
#include <boost/uuid/uuid.hpp> // uuid 类
#include <boost/uuid/uuid_generators.hpp> // 生成器
#include <boost/uuid/uuid_io.hpp> // 流输出/格式化
#include <iostream>
int main() {
// 声明一个 UUID 对象默认全零
boost::uuids::uuid id;
std::cout << "Default UUID: " << id << std::endl; // 输出00000000-0000-0000-0000-000000000000
return 0;
}

Boost 提供了多种符合 RFC 4122 的生成器
| 生成器类 | UUID 版本 | 描述 | 适用场景 |
|---|---|---|---|
random_generator | v4 | 基于强随机数 | 最常用需要高随机性且不关心时间/机器信息时 |
nil_generator | - | 生成全零 UUID | 作为占位符或未初始化状态 |
string_generator | - | 从字符串解析 | 反序列化、数据库读取 |
name_generator | v3/v5 | 基于命名空间和名称的 SHA-1 哈希 | 需要确定性、可重复生成的 ID如内容寻址 |
#include <boost/uuid/random_generator.hpp> #include <boost/uuid/uuid_io.hpp> boost::uuids::random_generator gen; boost::uuids::uuid id = gen(); // 每次调用生成一个随机的 v4 UUID std::cout << "Random UUID (v4): " << id << std::endl; // 示例输出f47ac10b-58cc-4372-a567-0e02b2c3d479
#include <boost/uuid/uuid_generators.hpp> // 注意需要链接 Boost.Date_Time 库 boost::uuids::uuid id = boost::uuids::random_generator()(); // v1 生成器已不推荐通常用 v4 // 现代实践中v1 较少使用因其会暴露 MAC 地址信息。
#include <boost/uuid/name_generator.hpp>
#include <boost/uuid/uuid.hpp>
// 定义命名空间 UUID例如 DNS 命名空间
boost::uuids::uuid ns_dns = { /* DNS namespace UUID: 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */
0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
};
// 创建 v5 (SHA-1) 名称生成器
boost::uuids::name_generator_v5 gen_v5(ns_dns);
boost::uuids::uuid id_v5 = gen_v5("www.example.com");
std::cout << "Name-based UUID (v5): " << id_v5 << std::endl;
// 对于相同的命名空间和名称生成的 UUID 永远相同。
#include <boost/uuid/string_generator.hpp>
#include <sstream>
boost::uuids::string_generator str_gen;
// 从标准格式字符串解析
std::string uuid_str = "123e4567-e89b-12d3-a456-426614174000";
boost::uuids::uuid id = str_gen(uuid_str);
// 验证解析是否成功无效字符串会抛出异常
try {
auto id2 = str_gen("invalid-uuid-string");
} catch (const std::runtime_error& e) {
std::cerr << "Parse failed: " << e.what() << std::endl;
}
// 自定义格式化无连字符
std::stringstream ss;
ss << std::hex << std::nouppercase << std::setfill('0');
for (unsigned char byte : id) {
ss << std::setw(2) << static_cast<int>(byte);
}
std::cout << "Raw hex: " << ss.str() << std::endl;
boost::uuid 本质上是一个 std::array<unsigned char, 16> 的类型别名占用 16 字节 连续内存适合作为值类型传递和存储。
static_assert(sizeof(boost::uuids::uuid) == 16, "UUID must be 16 bytes"); static_assert(std::is_trivially_copyable_v<boost::uuids::uuid>, "UUID should be trivially copyable");
#include <boost/uuid/uuid.hpp> #include <unordered_map> // Boost 已为 uuid 特化了 std::hash std::unordered_map<boost::uuids::uuid, std::string> cache; boost::uuids::random_generator gen; auto key = gen(); cache[key] = "some_data"; // 也可以使用 boost::hash需包含 <boost/functional/hash.hpp> #include <boost/functional/hash.hpp> size_t h = boost::hash<boost::uuids::uuid>()(key);
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/array.hpp>
#include <fstream>
struct MyData {
boost::uuids::uuid id;
int value;
template<class Archive>
void serialize(Archive& ar, const unsigned int version) {
ar & id & value;
}
};
// 保存
MyData data{gen(), 42};
std::ofstream ofs("data.txt");
boost::archive::text_oarchive oa(ofs);
oa << data;
// 加载
std::ifstream ifs("data.txt");
boost::archive::text_iarchive ia(ifs);
MyData loaded;
ia >> loaded;
boost::uuids::random_generator 内部使用 boost::random::random_device 或 boost::random::mt19937 作为随机源。对于高性能多线程场景
// 方案1每个线程使用独立的生成器推荐
thread_local boost::uuids::random_generator tls_gen;
// 方案2使用静态生成器并加锁性能较低
static boost::uuids::random_generator static_gen;
static std::mutex mtx;
{
std::lock_guard<std::mutex> lock(mtx);
auto id = static_gen();
}
boost::uuids::uuid id;
if (id.is_nil()) {
std::cout << "UUID is nil (uninitialized)" << std::endl;
}
boost::uuids::uuid id = gen(); auto version = id.version(); // 返回 1, 3, 4, 5 或 0未知 auto variant = id.variant(); // 返回 variant 类型通常为 RFC 4122 变体
不敏感。string_generator 解析时忽略大小写但 operator<< 输出默认小写。可使用 std::uppercase 控制输出格式。
建议存储为 16 字节的 BINARY(16) 或 36 字节的 CHAR(36)包含连字符。前者更节省空间且查询更快。
-- MySQL
CREATE TABLE items (
id BINARY(16) PRIMARY KEY,
name VARCHAR(255)
);
-- 插入时使用 UUID 的字节数组
INSERT INTO items (id, name) VALUES (UNHEX(REPLACE('f47ac10b-58cc-4372-a567-0e02b2c3d479', '-', '')), 'test');
boost::uuids::uuid id = gen();
// 遍历字节
for (unsigned char byte : id) {
std::cout << std::hex << static_cast<int>(byte) << ' ';
}
// 转换为字节数组C++17
std::array<unsigned char, 16> arr = *reinterpret_cast<std::array<unsigned char, 16>*>(&id);
#include <string_view>
std::string str = to_string(id);
std::string_view sv(str);
// 避免复制直接操作字符串视图
if (sv.starts_with("123e")) {
// ...
}
// 等待 Boost 适配 std::format目前可自定义
#include <fmt/format.h> // 或 {fmt} 库
template <>
struct fmt::formatter<boost::uuids::uuid> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
auto format(const boost::uuids::uuid& id, FormatContext& ctx) {
return format_to(ctx.out(), "{}", to_string(id));
}
};
// 使用
boost::uuids::uuid id = gen();
std::string s = fmt::format("UUID: {}", id);
thread_local 生成器避免锁竞争。operator<< 以便于调试输出。<uuid> 提案但 Boost 版本仍是当前事实标准。#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/functional/hash.hpp>
#include <boost/random.hpp>
namespace bu = boost::uuids;
void print_uuid_bytes(const bu::uuid& u)
{
std::cout << "Raw Bytes: ";
const std::uint8_t* p = u.data();
for (std::size_t i = 0; i < 16; ++i)
{
printf("%02X ", p[i]);
}
std::cout << "n";
}
int main()
{
// 1. Nil UUID只用默认构造不写 () / {} 避免歧义
bu::uuid nil_uuid;
std::cout << "1. Nil UUID: " << nil_uuid << "n";
std::cout << "is_nil() = " << std::boolalpha << nil_uuid.is_nil() << "n";
print_uuid_bytes(nil_uuid);
std::cout << "----------------------------------------nn";
// 2. V4 随机 UUID
bu::random_generator v4_gen;
bu::uuid v4_uuid = v4_gen();
std::cout << "2. V4 Random UUID: " << v4_uuid << "n";
print_uuid_bytes(v4_uuid);
// 自定义 mt19937 随机源
boost::random::mt19937 mt_rng(12345);
bu::basic_random_generator<boost::random::mt19937> seeded_gen(mt_rng);
bu::uuid seeded_v4 = seeded_gen();
std::cout << "Custom seeded V4 UUID: " << seeded_v4 << "n";
std::cout << "----------------------------------------nn";
// 4. 字符串解析 UUID
std::string uuid_str = "550e8400-e29b-41d4-a716-446655440000";
bu::string_generator str_gen;
bu::uuid from_str = str_gen(uuid_str);
std::cout << "4. Parse from string: " << from_str << "n";
print_uuid_bytes(from_str);
std::cout << "----------------------------------------nn";
// 5. 二进制缓冲区构造 UUID
std::vector<std::uint8_t> bin_data = {
0x55,0x0e,0x84,0x00,0xe2,0x9b,0x41,0xd4,
0xa7,0x16,0x44,0x66,0x55,0x44,0x00,0x00
};
bu::uuid from_bin;
std::copy(bin_data.begin(), bin_data.end(), from_bin.data());
std::cout << "5. Construct from binary buffer: " << from_bin << "n";
print_uuid_bytes(from_bin);
std::cout << "----------------------------------------nn";
// 6. UUID 字符串互转
std::string s = bu::to_string(v4_uuid);
std::cout << "6. to_string(): " << s << "n";
std::wstring ws = bu::to_wstring(v4_uuid);
std::wcout << L"to_wstring(): " << ws << L"n";
std::stringstream ss;
ss << v4_uuid;
std::string s_ss = ss.str();
std::cout << "stringstream output: " << s_ss << "n";
std::cout << "----------------------------------------nn";
// 7. 比较运算符
bu::uuid u1 = v4_gen();
bu::uuid u2 = v4_gen();
std::cout << "7. Compare Operatorsn";
std::cout << "u1 = " << u1 << "n";
std::cout << "u2 = " << u2 << "n";
std::cout << "u1 == u2: " << (u1 == u2) << "n";
std::cout << "u1 != u2: " << (u1 != u2) << "n";
std::cout << "u1 < u2: " << (u1 < u2) << "n";
std::cout << "u1 > u2: " << (u1 > u2) << "n";
std::cout << "----------------------------------------nn";
// 8. hash 无序容器
std::cout << "8. unordered_map with boost::hash<uuid>n";
std::unordered_map<bu::uuid, std::string, boost::hash<bu::uuid>> uuid_map;
uuid_map[v4_uuid] = "V4 random";
uuid_map[from_str] = "parsed string uuid";
for (const auto& pair : uuid_map)
{
std::cout << "Key: " << pair.first << " | Val: " << pair.second << "n";
}
std::cout << "----------------------------------------nn";
// 9. 修改原始字节
std::cout << "9. Modify raw bytes via data()n";
bu::uuid mod_uuid = v4_uuid;
std::uint8_t* mod_buf = mod_uuid.data();
mod_buf[0] = 0xFF;
mod_buf[1] = 0xAA;
std::cout << "Modified UUID: " << mod_uuid << "n";
print_uuid_bytes(mod_uuid);
std::cout << "----------------------------------------nn";
// 10. 二进制序列化/反序列化
std::cout << "10. Binary serialize & restoren";
std::uint8_t buf[16] = { 0 };
std::copy(v4_uuid.data(), v4_uuid.data() + 16, buf);
bu::uuid restore_uuid;
std::copy(buf, buf + 16, restore_uuid.data());
std::cout << "Original: " << v4_uuid << "n";
std::cout << "Restored: " << restore_uuid << "n";
std::cout << "Equal: " << (v4_uuid == restore_uuid) << "n";
return 0;
}
1. Nil UUID: 00000000-0000-0000-0000-000000000000 is_nil() = true Raw Bytes: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ---------------------------------------- 2. V4 Random UUID: dbf8440f-089a-472a-aee4-ebf1bc6446ea Raw Bytes: DB F8 44 0F 08 9A 47 2A AE E4 EB F1 BC 64 46 EA Custom seeded V4 UUID: e251fbed-e52d-41e3-9dfd-fd5081087621 ---------------------------------------- 4. Parse from string: 550e8400-e29b-41d4-a716-446655440000 Raw Bytes: 55 0E 84 00 E2 9B 41 D4 A7 16 44 66 55 44 00 00 ---------------------------------------- 5. Construct from binary buffer: 550e8400-e29b-41d4-a716-446655440000 Raw Bytes: 55 0E 84 00 E2 9B 41 D4 A7 16 44 66 55 44 00 00 ---------------------------------------- 6. to_string(): dbf8440f-089a-472a-aee4-ebf1bc6446ea to_wstring(): dbf8440f-089a-472a-aee4-ebf1bc6446ea stringstream output: dbf8440f-089a-472a-aee4-ebf1bc6446ea ---------------------------------------- 7. Compare Operators u1 = 610f7ff1-9b09-46fa-ba27-cb4bae9cf2e6 u2 = 98b7d23f-eb1f-4244-a04c-2c8555e7ad2b u1 == u2: false u1 != u2: true u1 < u2: true u1 > u2: false ---------------------------------------- 8. unordered_map with boost::hash<uuid> Key: dbf8440f-089a-472a-aee4-ebf1bc6446ea | Val: V4 random Key: 550e8400-e29b-41d4-a716-446655440000 | Val: parsed string uuid ---------------------------------------- 9. Modify raw bytes via data() Modified UUID: ffaa440f-089a-472a-aee4-ebf1bc6446ea Raw Bytes: FF AA 44 0F 08 9A 47 2A AE E4 EB F1 BC 64 46 EA ---------------------------------------- 10. Binary serialize & restore Original: dbf8440f-089a-472a-aee4-ebf1bc6446ea Restored: dbf8440f-089a-472a-aee4-ebf1bc6446ea Equal: true D:user1417804桌面新建文件夹Project1x64DebugProject1.exe (进程 76000)已退出代码为 0 (0x0)。 要在调试停止时自动关闭控制台请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。 按任意键关闭此窗口. . .
