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

使用初始化列表初始化std::unique_ptr容器问题续(std::map场景)

分析std::map初始化std::unique_ptr<T>失败的原因

Hey there! Let's dig into why your initial std::map setup with std::unique_ptr failed, while the std::vector version worked perfectly. First, let's recap the code snippets you provided, then break down the root cause.

可行的std::vector初始化代码

This one works smoothly thanks to how vector handles initialization lists and unique_ptr's move semantics:

#include <vector>
#include <memory>

int main() {
    std::vector<std::unique_ptr<int>> vec = {
        std::make_unique<int>(1),
        std::make_unique<int>(2),
        std::make_unique<int>(3)
    };
    return 0;
}

报错的std::map初始化代码

This version throws a compile error tied to unique_ptr's deleted copy constructor:

#include <map>
#include <memory>

int main() {
    // 编译报错:尝试调用已被删除的unique_ptr拷贝构造函数
    std::map<int, std::unique_ptr<int>> map = {
        {1, std::make_unique<int>(1)},
        {2, std::make_unique<int>(2)},
        {3, std::make_unique<int>(3)}
    };
    return 0;
}

A typical error message looks like:

use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'

调试成功的std::map实现

Here are the working approaches you landed on:

#include <map>
#include <memory>

int main() {
    // 方式1:显式用std::move转移所有权
    std::map<int, std::unique_ptr<int>> map1 = {
        {1, std::move(std::make_unique<int>(1))},
        {2, std::move(std::make_unique<int>(2))},
        {3, std::move(std::make_unique<int>(3))}
    };

    // 方式2:用emplace直接在map内存中构造元素
    std::map<int, std::unique_ptr<int>> map2;
    map2.emplace(1, std::make_unique<int>(1));
    map2.emplace(2, std::make_unique<int>(2));
    map2.emplace(3, std::make_unique<int>(3));

    // 方式3:显式构造pair对象
    std::map<int, std::unique_ptr<int>> map3 = {
        std::pair<int, std::unique_ptr<int>>(1, std::make_unique<int>(1)),
        std::pair<int, std::unique_ptr<int>>(2, std::make_unique<int>(2))
    };
    return 0;
}

核心原因:vector与map初始化逻辑的差异

First, remember that std::unique_ptr is an exclusive-ownership smart pointer—its copy constructor and copy assignment operator are explicitly deleted. It only supports move semantics to transfer ownership of the underlying pointer.

为什么vector代码能正常运行

When you initialize a vector with {std::make_unique(...), ...}, the compiler directly constructs unique_ptr objects in the vector's internal memory. The make_unique calls return rvalues (temporary objects), and the vector's initializer-list constructor can move these rvalues into place using unique_ptr's valid move constructor. No copy operations are attempted here.

为什么原始map代码失效

std::map stores elements as std::pair<const Key, T> (in your case, pair<const int, unique_ptr<int>>). When you write { {1, make_unique(1)}, ... }, the compiler first tries to construct temporary pair objects from each nested initializer list.

The problem? When initializing the pair's second member (the unique_ptr), the compiler tries to copy the temporary unique_ptr returned by make_unique into the pair. Since unique_ptr's copy constructor is deleted, this triggers a compile error.

Unlike vector, the initializer-list handling for map doesn't automatically move the rvalue into the pair—it treats initializer list elements as const references, which can't trigger a move operation.

为什么修复后的map代码能工作

  • std::move方式: Explicitly casts the temporary unique_ptr to an rvalue reference, forcing the pair constructor to use unique_ptr's move constructor instead of attempting a copy.
  • emplace方式: Constructs the pair directly in the map's memory, skipping temporary pair objects entirely. This transfers ownership of the unique_ptr directly into the map's element without any copy attempts.
  • 显式构造pair方式: When you explicitly create a pair with an rvalue unique_ptr, the pair's constructor uses move semantics to take ownership of the pointer, avoiding copies.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:50:42