You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 22:33:25