唯一标准方式是std::this_thread::get_id(),返回std::thread::id对象,支持比较和哈希;主线程id合法且同线程多次调用结果相同;std::thread::get_id()仅对已启动线程有效,判断运行状态应使用joinable()而非id比较。

std::this_thread::get_id() 是唯一标准方式
在 C++11 及之后,获取当前线程 ID 的标准、可移植、线程安全的方法只有 std::this_thread::get_id()。它返回一个 std::thread::id 类型对象,不是整数,也不是指针——这点容易误解。
常见错误是试图用 pthread_self() 或 GetCurrentThreadId() 混用,但这些属于平台 API,和 std::thread 对象无直接关联,且 std::thread::id 的内部表示由实现定义(可能封装了原生句柄,也可能不)。
-
std::this_thread::get_id()返回值可直接比较(==/!=),也可用于std::map或std::unordered_map(需配合std::hash<:thread::id></:thread::id>) - 不能假设
std::thread::id可隐式转为unsigned long或void*;若真需数字标识(如日志打点),应调用.hash()方法得到std::size_t - 主线程也拥有合法的
std::thread::id,多次调用std::this_thread::get_id()在同一线程中返回相同值
std::thread::get_id() 只对已启动的 thread 对象有效
std::thread 对象的成员函数 get_id() 返回的是该对象所代表线程的 ID,但它**不等于当前执行线程的 ID**——除非你正在那个线程里调用它。更关键的是:如果 std::thread 对象尚未启动(比如刚构造完、或已 join() / detach() 过),其 get_id() 返回 std::thread::id()(空 ID,等价于默认构造的 std::thread::id)。
- 判断一个
std::thread是否正在运行,应写成:t.joinable(),而不是t.get_id() != std::thread::id()(虽然后者常能凑效,但语义不准确) -
t.get_id()和std::this_thread::get_id()相等,仅当t正在当前线程中执行(例如在t绑定的函数体内) - 移动一个
std::thread后,原对象的get_id()变为空,新对象继承原线程 ID
日志/调试中打印 thread id 要用 .hash() 或流输出
std::thread::id 本身不支持直接 std::cout (C++11 到 C++17 中部分标准库实现提供流操作符,但非强制;C++20 起才保证支持)。更可靠、可移植的做法是:
立即学习“C++免费学习笔记(深入)”;
- 调试时用
std::cout —— 多数现代 libstd<a style="color:#f60; text-decoration:underline;" title="c++" href="https://www.php.cn/zt/17603.html" target="_blank">c++</a> / libc++ 已实现,输出形如 <code>1234567890(十进制)或十六进制地址,但格式不跨平台 - 日志中需要稳定数字标识,用
std::hash<:thread::id>{}(std::this_thread::get_id())</:thread::id>,结果是std::size_t,可安全转为uint64_t打印 - 避免用
reinterpret_cast<uintptr_t>(&some_local_var)</uintptr_t>猜测线程 ID,这是未定义行为
Windows 和 Linux 下底层 ID 不可互换
虽然 std::this_thread::get_id() 在所有平台上语义一致,但它的底层实现差异很大:
- Linux 上,libstdc++ 通常把
pthread_t直接存入std::thread::id(pthread_t是结构体,非纯整数);libc++ 可能做哈希映射 - Windows 上,MSVC 的
std::thread::id一般包装DWORD(即线程内核句柄 ID),但不保证与GetCurrentThreadId()返回值相同(后者是用户态 ID,更轻量) - 因此,绝不要把
std::thread::id强转为pthread_t*或DWORD去调用系统 API;如需原生句柄,应从std::thread构造时保存,或用平台专用方式获取
真正跨平台的线程身份标识,只应基于 std::thread::id 的相等性或哈希值,而非其二进制布局或数值含义。










