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

嵌套make_unique调用触发std::uninitialized_copy()失败问题排查

问题:std::unique_ptr作为容器元素时的编译失败问题

我是C++新手,想把std::unique_ptr作为std::vector这类支持移动的容器元素,存储动态分配的对象来实现多态。但把Animal类的成员actions改成std::vector<std::unique_ptr<Action>>时编译失败,报错指向std::uninitialized_copy();换成std::vector<Action>就能正常编译。错误出现在World构造函数调用std::make_unique<Person>(first)的时候,推测和first.actions里的std::unique_ptr处理有关。查了很多std::unique_ptr的资料,但没找到这种嵌套场景的参考,需要入门级的解决提示。

可编译代码(切换注释可触发编译失败/成功)

#include<vector>
#include<memory>

class Entity;

class Action
{
    public:
        Action() = default;
};

class World {
    std::vector<std::unique_ptr<Entity>> entities;
    public:
        World();
};

class Entity {
    public:
        Entity() = default;
};

class Animal: public Entity {
    protected:
        // 编译失败的版本 - 错误日志见下方
        std::vector<std::unique_ptr<Action>> actions;
        // 可正常编译但不支持多态的版本
        //std::vector<Action> actions;
    public:
        Animal() = default;
};

class Person: public Animal
{
    protected:
        World& world;
    public: 
        Person(World& world);
};

Person::Person(World& world) : world(world)
{
}

World::World()
{
    Person first = Person(*this);
    entities.push_back(std::make_unique<Person>(first));
}

编译错误信息

/usr/include/c++/9/bits/stl_uninitialized.h|307 col 37 error| required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<Action>*, std::vector<std::unique_ptr<Action>> >; _ForwardIterator = std::unique_ptr<Action>*; _Tp = std::unique_ptr<Action>]’
/usr/include/c++/9/bits/stl_vector.h|555 col 31 error| required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<Action>; _Alloc = std::allocator<std::unique_ptr<Action>>]’
test.cpp|23 col 7 error| required from ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = Person; _Args = {Person&}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<Person, std::default_delete<Person>>]’
test.cpp|48 col 54 error| required from here
/usr/include/c++/9/bits/stl_uninitialized.h|127 col 72 error| static assertion failed: result type must be constructible from value type of input range

解决方向提示

  • 核心原因:std::unique_ptr是不可拷贝的类型。你的代码中,Person first = Person(*this)创建了一个Person对象,之后调用std::make_unique<Person>(first)尝试拷贝这个Person对象。由于Person继承自Animal,Animal中的std::vector<std::unique_ptr<Action>>因为元素不可拷贝,导致整个vector的拷贝构造函数被禁用,进而Person的拷贝构造函数也被编译器自动禁用,触发编译错误。
  • 方案1:用移动语义替代拷贝
    修改World构造函数中的代码,将拷贝改为移动:
    World::World()
    {
        Person first = Person(*this);
        entities.push_back(std::make_unique<Person>(std::move(first)));
    }
    
    std::move会将first转为右值,触发Person的移动构造函数(编译器会自动生成),而std::vector支持移动操作,内部的unique_ptr也会被移动而非拷贝,从而正常编译。
  • 方案2:直接构造对象,避免中间拷贝
    去掉中间的first对象,直接在make_unique中构造Person:
    World::World()
    {
        entities.push_back(std::make_unique<Person>(*this));
    }
    
    这样绕开了拷贝操作,直接将新构造的Person对象移动到unique_ptr中。
  • 额外提示:如果后续需要自定义Person的拷贝/移动逻辑,记得显式定义移动构造函数,确保std::vector<std::unique_ptr<Action>>被正确移动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:25:35