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

原地创建含unique_ptr的对象时MSVC编译失败问题咨询

MSVC 2019早期版本emplace_back含unique_ptr的unordered_map编译错误分析

没错,这确实是MSVC 2019 16.2.1版本的编译器Bug,属于标准库实现对C++移动语义的处理失误。

问题到底出在哪?

当你试图用emplace_back向vector里构造std::unordered_map<int, std::unique_ptr<int>>时,MSVC的标准库底层错误地尝试调用了std::pair的拷贝构造函数——而std::pair里包含不可拷贝的std::unique_ptr,直接触发了C2280的“引用已删除函数”错误。

哪怕你用了原地构造的写法(比如emplace_back()或emplace_back(hash_int_uptr{})),早期MSVC的vector::emplace_back在处理嵌套容器类型时,没有正确走移动构造的逻辑,反而错误回退到了拷贝构造的路径上。

可行的解决办法

这里有几个靠谱的修复方案,按优先级推荐:

  • 优先升级MSVC版本:这个Bug在MSVC 2019 16.3及之后的版本里已经被官方修复了,升级编译器是一劳永逸的解决方式。
  • 显式强制移动语义:用std::move明确告诉编译器走移动路径,修改代码如下:
    #include <memory>
    #include <vector>
    #include <unordered_map>
    int main() {
        using hash_int_uptr = std::unordered_map<int, std::unique_ptr<int>>;
        std::vector<hash_int_uptr> v;
        v.push_back(std::move(hash_int_uptr{})); // 显式触发移动
    }
    
  • 临时对象手动转移:先创建一个局部临时对象,再通过std::move传入emplace_back,写法如下:
    hash_int_uptr temp;
    v.emplace_back(std::move(temp));
    

关于你的几个对比场景

你提到的几个测试结果正好能佐证这个Bug的特殊性:

  • 换成std::shared_ptr能正常编译,是因为shared_ptr本身支持拷贝,就算编译器错误调用拷贝构造也不会触发删除函数的报错。
  • 直接emplace_back单个unique_ptr没问题,是因为vector处理单个unique_ptr的emplace逻辑没有触发这个针对容器内部pair的拷贝Bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:52:46