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

C++智能指针与vector多态问题:插入unique_ptr触发C2664编译错误

解决std::unique_ptr存入vector时的C2664编译错误

嘿,这个编译错误我太熟了——你这是踩了std::unique_ptr最核心的特性坑:它是独占式智能指针,不允许被拷贝,而你试图把它直接拷贝进vector,编译器当然要报错啦!

错误原因拆解

你看到的Error C2664本质是:std::unique_ptr的拷贝构造函数是被显式删除的(= delete),因为它设计的初衷就是确保同一时间只有一个unique_ptr拥有对象的所有权。如果你写了类似vec.push_back(my_ptr);这样的代码,编译器会尝试调用拷贝构造,这直接违反了unique_ptr的设计规则,所以必然报错。

针对你的场景的解决方案

你的需求是解析文件创建不同子类对象,存入vector<unique_ptr<基类>>,这里有几种安全且符合规范的写法:

1. 直接在push_back中构造并转移所有权

用std::make_unique直接创建智能指针,然后把它的所有权转移给vector——因为make_unique返回的是右值,push_back会自动调用移动构造(而不是拷贝):

std::vector<std::unique_ptr<Test>> obj_vec;

// 解析到字符'A'时创建SubTestA对象
if (parsed_char == 'A') {
    obj_vec.push_back(std::make_unique<SubTestA>());
}

2. 用std::move显式转移所有权

如果你需要先对智能指针做一些初始化操作,再存入vector,可以用std::move把局部指针的所有权转移给容器元素:

auto ptr = std::make_unique<SubTestB>();
// 这里可以对ptr指向的对象做一些初始化操作
ptr->init_some_data();

// 显式转移所有权,之后ptr就变成空指针了,不能再使用它
obj_vec.push_back(std::move(ptr));

3. 用emplace_back直接在容器内构造对象

emplace_back可以直接在vector的内存空间里构造unique_ptr,比push_back更高效(减少一次移动操作):

// 直接在vector内构造SubTestA的unique_ptr
obj_vec.emplace_back(std::make_unique<SubTestA>());

// 或者直接用new(但更推荐make_unique,避免内存泄漏风险)
obj_vec.emplace_back(new SubTestA());

必加的关键细节:基类的虚析构函数

因为你用基类指针指向子类对象,一定要给基类Test添加虚析构函数,否则unique_ptr销毁对象时只会调用基类的析构函数,导致子类的资源无法正确释放,引发未定义行为:

class Test {
public:
    // 虚析构函数,确保子类对象能被正确销毁
    virtual ~Test() = default;
    // 其他纯虚接口函数...
};

完整示例代码

#include <vector>
#include <memory>
#include <fstream>

// 基类必须有虚析构
class Test {
public:
    virtual ~Test() = default;
    virtual void process() = 0; // 纯虚接口
};

class SubTestA : public Test {
public:
    void process() override {
        // SubTestA的处理逻辑
    }
};

class SubTestB : public Test {
public:
    void process() override {
        // SubTestB的处理逻辑
    }
};

int main() {
    std::vector<std::unique_ptr<Test>> objects;
    std::ifstream input_file("your_file.txt");
    char type;

    while (input_file >> type) {
        switch (type) {
            case 'A':
                objects.emplace_back(std::make_unique<SubTestA>());
                break;
            case 'B':
                auto ptr = std::make_unique<SubTestB>();
                // 可以在这里做初始化
                objects.push_back(std::move(ptr));
                break;
            default:
                // 处理未知类型
                break;
        }
    }

    // 遍历调用子类方法
    for (const auto& obj : objects) {
        obj->process();
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:34:04