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

低版本MSVC中std::async编译失败,如何解决?

问题:如何让指定C++代码在MSVC 19.29版本下编译通过?

原代码

#include <vector>
#include <algorithm>
#include <thread>
#include <future>
#include <iostream>


int main() {
    std::vector<int> v(1000);
    for(unsigned i = 0; i < v.size(); i++) {
        v[i] = i;
    }
    int bb = 2;
    std::cout << v.back() << std::endl;
    auto f = [&](int& x) {x = 2*x; bb=4; };
    
    std::async(std::launch::async, std::for_each<decltype(v.begin()),decltype(f)>,
           v.begin(), v.end(), f);

    std::cout << v.back() << std::endl;
    std::cout << "bb: " << bb;
    return 0;
}

编译失败情况

上述代码可在GCC、ICC、Clang及MSVC 19.32+版本正常编译(需链接-lpthread),但在MSVC 19.29版本下编译失败,报错信息如下:

example.cpp
<source>(16): warning C4834: discarding return value of function with 'nodiscard' attribute
C:/data/msvc/14.31.31108/include\future(314): error C2280: 'main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37> &main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>::operator =(const main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37> &)': attempting to reference a deleted function
<source>(14): note: see declaration of 'main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>::operator ='
<source>(14): note: 'main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37> &main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>::operator =(const main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37> &)': function was explicitly deleted
C:/data/msvc/14.31.31108/include\future(309): note: while compiling class template member function 'void std::_Associated_state<_Ty>::_Set_value_raw(_Ty &&,std::unique_lock<std::mutex> *,bool)'
        with
        [
            _Ty=main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>
        ]
C:/data/msvc/14.31.31108/include\future(305): note: see reference to function template instantiation 'void std::_Associated_state<_Ty>::_Set_value_raw(_Ty &&,std::unique_lock<std::mutex> *,bool)' being compiled
        with
        [
            _Ty=main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>
        ]
C:/data/msvc/14.31.31108/include\future(722): note: see reference to class template instantiation 'std::_Associated_state<_Ty>' being compiled
        with
        [
            _Ty=main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>
        ]
C:/data/msvc/14.31.31108/include\future(720): note: while compiling class template member function 'std::_State_manager<_Ty>::~_State_manager(void) noexcept'
        with
        [
            _Ty=main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>
        ]
C:/data/msvc/14.31.31108/include\future(879): note: see reference to function template instantiation 'std::_State_manager<_Ty>::~_State_manager(void) noexcept' being compiled
        with
        [
            _Ty=main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>
        ]
C:/data/msvc/14.31.31108/include\future(860): note: see reference to class template instantiation 'std::_State_manager<_Ty>' being compiled
        with
        [
            _Ty=main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>
        ]
<source>(17): note: see reference to class template instantiation 'std::future<main::<lambda_fa7e30e7ff267c277ebbd82c8a7f9e37>>' being compiled

解决方案

编译失败的核心原因是:旧版MSVC的std::async实现会尝试拷贝捕获了引用的lambda,而这类lambda的拷贝赋值运算符默认被删除,导致编译报错。以下是两种可行的修改方案:

方案一:用std::ref传递lambda(推荐)

将lambda通过std::ref包装后传递给std::async,同时去掉std::for_each的显式模板参数(让编译器自动推导更安全),修改后的代码行如下:

std::async(std::launch::async, std::for_each, v.begin(), v.end(), std::ref(f));

这种方式传递的是lambda的引用,避免了拷贝操作,旧版MSVC可以正确处理,同时保留原逻辑的正确性。

方案二:让lambda支持拷贝(不推荐)

手动为lambda添加拷贝构造和拷贝赋值运算符,但需要注意:原lambda捕获了局部变量的引用,拷贝后的lambda在异步线程中使用可能因变量生命周期问题导致悬空引用,引发未定义行为,因此仅在特殊场景下考虑此方案。

内容的提问来源于stack exchange,提问作者helios

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 07:00:59