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

Visual-C++中std::promise::set_value执行后成员unique_ptr为空问题

问题根因

  • MSVC STL的tuple实现缺陷:VS2019及更早版本的MSVC标准库中,对包含仅移动类型(如std::unique_ptr)的tuple的完美转发、移动赋值逻辑存在已知bug。当std::forward<_Ty>(_Val)执行时,可能出现tuple部分成员被提前移动为空、未正确赋值到目标_Result的问题。Clang使用的libc++/libstdc++没有该实现问题,因此不会复现。
  • 类型隐式转换问题:如果std::promise声明的模板参数类型,和你传入set_value的实际tuple类型不完全匹配(比如自定义类型的cv限定符不一致、tuple长度/元素类型隐式可转换但不完全一致),MSVC会生成临时tuple对象完成转换,转换过程中可能错误触发部分成员的移动语义,导致最终_Result丢失mFoo的所有权。
  • 调试器显示误差:部分版本的MSVC调试器在观测嵌套unique_ptr的tuple结构时,会错误将有效指针显示为nullptr,你可以通过std::future::get获取结果后实际访问mFoo确认是否真的为空,排除调试器的干扰。

修复方案

  • 升级到Visual Studio 2022 17.4及以上版本,微软已在新版MSVC STL中修复了大量tuple移动、转发相关的缺陷。
  • 确保std::promise的模板参数类型和传入set_value的参数类型完全一致,调用时显式使用std::move转移所有权,避免隐式转换:
    // 示例:promise类型与传入参数完全匹配,显式移动
    std::promise<std::tuple<MyCustomType>> pr;
    std::tuple<MyCustomType> val = {MyCustomType{...}};
    pr.set_value(std::move(val));
    
  • 若暂时无法升级编译器,可以将存储用的tuple替换为自定义结构体,绕开MSVC tuple的实现问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:30:05