为何cppreference的future.wait_until示例用thread.detach()?会内存泄漏吗?
关于cppreference中std::future::wait_until示例使用detach()的疑问解答
问题背景
在cppreference的std::future::wait_until示例代码中,创建线程后调用了detach()方法,代码及疑问如下:
示例代码(已翻译注释)
#include <iostream> #include <future> #include <thread> #include <chrono> int main() { std::chrono::system_clock::time_point two_seconds_passed = std::chrono::system_clock::now() + std::chrono::seconds(2); // 创建一个1秒后完成的future std::promise<int> p1; std::future<int> f_completes = p1.get_future(); std::thread([](std::promise<int> p1) { std::this_thread::sleep_for(std::chrono::seconds(1)); p1.set_value_at_thread_exit(9); }, std::move(p1) ).detach(); // 创建一个5秒后完成的future std::promise<int> p2; std::future<int> f_times_out = p2.get_future(); std::thread([](std::promise<int> p2) { std::this_thread::sleep_for(std::chrono::seconds(5)); p2.set_value_at_thread_exit(8); }, std::move(p2) ).detach(); std::cout << "等待2秒..." << std::endl; if(std::future_status::ready == f_completes.wait_until(two_seconds_passed)) { std::cout << "f_completes已完成: " << f_completes.get() << "\n"; } else { std::cout << "f_completes未完成!\n"; } if(std::future_status::ready == f_times_out.wait_until(two_seconds_passed)) { std::cout << "f_times_out已完成: " << f_times_out.get() << "\n"; } else { std::cout << "f_times_out未完成!\n"; } std::cout << "结束!\n"; }
疑问点
- 为何要使用
detach()? - 这是否会导致线程内存泄漏?
- 这种写法似乎不符合常规认知,为什么cppreference会这么写?
解答
1. 使用detach()的原因
核心是避免主线程结束时触发程序崩溃。
C++标准规定:如果std::thread对象析构时,其关联的线程仍在运行且未被join()或detach(),会直接调用std::terminate()终止整个程序。
这个示例的主线程逻辑是等待2秒后检查future状态,随后直接退出。此时第二个子线程(需要运行5秒)肯定还在运行,若不调用detach(),主线程结束时std::thread对象析构,就会触发程序崩溃。detach()的作用是让子线程与std::thread对象解除关联,线程在后台独立运行,不会因std::thread对象的析构而终止程序。
2. 不会导致内存泄漏
detach()只是解除线程与std::thread对象的关联,不存在内存泄漏:
- 线程自身的资源(栈空间、线程控制块等)会在线程结束时由操作系统自动回收;
- 子线程中的
std::promise是通过移动语义传递的,线程结束时promise会被正常析构,set_value_at_thread_exit确保在线程退出前完成值的设置,所有资源都会正确释放; - 示例中没有动态分配的内存未被释放,不存在内存泄漏场景。
3. 关于“不符合常规认知”的说明
常规开发中我们更倾向于用join()等待子线程完成,确保逻辑执行完毕、资源回收,但这个示例的核心目标是演示wait_until的超时行为:
- 示例只需要展示等待2秒时,第一个future就绪、第二个future超时的状态;
- 子线程后续的执行(比如第二个子线程剩余的3秒运行时间)不影响核心演示意图;
- cppreference的示例优先聚焦目标API的功能展示,因此用
detach()简化写法,避免不必要的join()逻辑干扰核心代码的可读性。
内容的提问来源于stack exchange,提问作者flobacca
相关产品推荐
相关产品推荐

