嵌套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:
这样绕开了拷贝操作,直接将新构造的Person对象移动到unique_ptr中。World::World() { entities.push_back(std::make_unique<Person>(*this)); } - 额外提示:如果后续需要自定义Person的拷贝/移动逻辑,记得显式定义移动构造函数,确保
std::vector<std::unique_ptr<Action>>被正确移动。
内容的提问来源于stack exchange,提问作者markdwhite
相关产品推荐
相关产品推荐

