std::async默认不真正异步,仅延迟求值;需显式指定std::launch::async才启用新线程,且future析构会阻塞等待,get()后失效,应避免误用。
async 会真的异步执行吗?
不会,std::async 默认行为是“延迟求值”(std::launch::deferred),也就是调用时并不启动新线程,而是在你调用 get() 或 wait() 时才同步执行——这根本不是异步。
必须显式指定 std::launch::async 才能真正启用新线程:
auto fut = std::async(std::launch::async, []{ return 42; });
- 漏写
std::launch::async是最常见错误,尤其在调试时发现任务卡主线程 - 不加参数或只传函数对象,等价于
std::launch::deferred | std::launch::async,系统可自由选择策略,行为不可控 - 某些平台(如 MinGW)对
std::launch::async支持不完整,可能退化为 deferred
future.get() 调用一次就失效
std::future 是一次性消费对象:调用 get() 后,其内部状态变为“已获取”,再次调用会抛出 std::future_error(错误码为 std::future_errc::no_state)。
典型错误场景:
立即学习“C++免费学习笔记(深入)”;
auto f = std::async(std::launch::async, []{ return 123; });
int a = f.get(); // ✅ 正常
int b = f.get(); // ❌ 抛异常:std::future_error
- 不能把同一个
future保存下来反复取结果 - 若需多次访问结果,应把
get()结果存入变量,或改用std::shared_future -
shared_future可拷贝,且所有副本共享同一状态,适合多处等待或读取
async 对象生命周期管理很关键
std::async 返回的 future 对象,其析构会**阻塞等待任务结束**——哪怕你没调用 get()。