含unique_ptr的对象如何存入vector?C++技术问题咨询
解决包含unique_ptr的类存入vector的编译错误
问题根源
std::unique_ptr是独占式智能指针,它的拷贝构造和拷贝赋值操作被显式禁用了。你的Character类包含unique_ptr<Weapon>成员,编译器会自动删除Character的默认拷贝构造函数。当你调用vector::push_back尝试拷贝Character对象时,就会触发编译错误。
解决方案(无需使用指针vector)
1. 利用移动语义(推荐,效率最高)
移动语义可以把Character对象的所有权转移到vector中,而不是拷贝。具体有两种实现方式:
方式一:通过右值引用传递对象并移动入vector
修改addPlayer函数接收右值引用,再用std::move完成所有权转移:
#include <iostream> #include <vector> #include <memory> #include <string> // 假设Weapon类定义如下 class Weapon { public: Weapon(const std::string& name, int range, int damage) : name(name), range(range), damage(damage) {} std::string name; int range; int damage; }; class Character { public: Character(const std::string& weaponName, int weaponRange, int weaponDamage) { _weapon = std::make_unique<Weapon>(weaponName, weaponRange, weaponDamage); } // 编译器会自动生成移动构造/赋值,因为unique_ptr支持移动 private: std::unique_ptr<Weapon> _weapon; }; std::vector<Character> _players; void addPlayer(Character&& character) { _players.push_back(std::move(character)); } int main() { // 临时对象本身是右值,直接传递 addPlayer(Character("长剑", 5, 10)); // 左值对象需要用std::move转为右值,转移后原对象的_weapon会失效 Character player("战斧", 3, 15); addPlayer(std::move(player)); return 0; }
方式二:直接在vector内存中构造对象(避免拷贝/移动)
使用vector::emplace_back直接在vector的内存空间里构造Character对象,完全跳过拷贝或移动步骤:
// 沿用上面的Weapon和Character类定义 std::vector<Character> _players; int main() { // 直接传入构造Character的参数,emplace_back会在vector内构造对象 _players.emplace_back("弓箭", 10, 8); return 0; }
2. 手动实现拷贝构造(需要对象拷贝场景)
如果你的游戏需要复制Character对象(比如两个角色持有相同属性但独立的Weapon),可以手动实现Character的拷贝构造函数,在拷贝时创建新的Weapon实例:
#include <iostream> #include <vector> #include <memory> #include <string> class Weapon { public: Weapon(const std::string& name, int range, int damage) : name(name), range(range), damage(damage) {} std::string name; int range; int damage; }; class Character { public: Character(const std::string& weaponName, int weaponRange, int weaponDamage) { _weapon = std::make_unique<Weapon>(weaponName, weaponRange, weaponDamage); } // 自定义拷贝构造函数:复制原对象的Weapon属性,创建新的Weapon Character(const Character& other) { _weapon = std::make_unique<Weapon>(*other._weapon); } // 配套实现拷贝赋值运算符 Character& operator=(const Character& other) { if (this != &other) { _weapon = std::make_unique<Weapon>(*other._weapon); } return *this; } private: std::unique_ptr<Weapon> _weapon; }; // 此时可以正常使用push_back拷贝对象 std::vector<Character> _players; void addPlayer(Character character) { _players.push_back(character); } int main() { Character player("匕首", 2, 7); addPlayer(player); // 正常拷贝,player的_weapon不受影响 return 0; }
方案选择
- 移动语义:适合不需要保留原对象的场景,仅转移指针所有权,无额外内存开销,效率最高。
- emplace_back:适合直接创建对象存入vector的场景,完全避免拷贝/移动操作。
- 自定义拷贝构造:适合需要复制对象的场景,但会产生新的Weapon实例,有一定内存开销。
内容的提问来源于stack exchange,提问作者KikiTheLord
相关产品推荐
相关产品推荐

