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

含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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:34:54