std::async实参的生命周期是怎样的?
关于std::async实参与future对象共享生命周期的测试发现
我最近做了个测试,发现一个挺有意思的细节:通过std::async执行函数时,传递的实参会和返回的std::future对象共享生命周期。也就是说,这些实参不会在std::async调用结束后立刻销毁,而是会一直存活到对应的future对象被销毁、或者调用了get()/wait()等完成操作之后。
下面是我用来验证这个现象的完整示例代码:
#include <iostream> #include <future> #include <thread> #include <cstdint> #include <chrono> struct S { S() { std::cout << "S() " << (uintptr_t)this << std::endl; } S(S&& s) { std::cout << "S(&&) " << (uintptr_t)this << std::endl; } S(const S& s) = delete; ~S() { std::cout << "~S() " << (uintptr_t)this << std::endl; } }; void func(S s) { std::cout << "func executing" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); } int main() { std::cout << "Creating S instance\n"; S s; std::cout << "Calling std::async\n"; auto fut = std::async(std::launch::async, func, std::move(s)); std::cout << "std::async called, main continues\n"; // 若注释掉下面的fut.get(),会看到实参的析构会在fut销毁时才触发 // fut.get(); std::cout << "Main about to exit scope\n"; }
输出分析(未调用fut.get()的情况):
Creating S instance S() 0x7ffeefbff5e8 Calling std::async S(&&) 0x55f8a7c2c2a0 std::async called, main continues Main about to exit scope ~S() 0x55f8a7c2c2a0 ~S() 0x7ffeefbff5e8
从输出能明确看到:
- main中创建的
S实例(地址0x7ffeefbff5e8)被移动到了std::async内部的实参对象(地址0x55f8a7c2c2a0) - 这个被移动后的实参并没有在
std::async调用结束后立刻销毁,而是等到main块结束、fut对象被销毁时才执行析构。
如果我们调用fut.get(),实参的析构会在get()返回后立刻发生——因为此时future的任务已经完成,不再需要持有实参的生命周期了。
这个细节需要特别注意:如果你传递的实参是持有文件句柄、内存等资源的对象,它的生命周期会和future绑定,可能会导致意外的资源占用,得提前做好规划。
内容的提问来源于stack exchange,提问作者Kentzo
相关产品推荐
相关产品推荐

