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

C++排序Workout对象vector触发C2280错误该如何修复?

问题原因分析

第一个C2280错误(Workout拷贝赋值被删除)

  • 根本原因:Workout类包含const int price成员,const类型成员初始化后不可修改,编译器会默认删除类的拷贝赋值运算符operator=。即使你手动实现了placement new版本的赋值运算符,这种写法属于非常规操作,不符合C++对const成员的语义约束。排序时需要交换元素,触发赋值操作就会报错。
  • 触发场景:你在order函数里创建了tmp向量拷贝workout_options,调用std::sort排序时,sort内部需要移动/交换Workout对象,触发了被删除的赋值运算符。

第二个unique_ptr版本C2280错误

  • 根本原因:std::unique_ptr是独占型智能指针,禁止拷贝构造和拷贝赋值,你写的排序lambda参数是按值传递unique_ptr<Workout> w1,会触发拷贝操作,调用了被删除的拷贝构造函数,所以报错。
修复方案

方案1:修改Workout类适配拷贝赋值(最简便)

把const成员price改成非const,只保留getPrice接口为const,对外仍然保证只读属性,同时可以使用默认的拷贝赋值运算符,不需要手动写placement new版本的赋值函数:

class Workout {
public:
    Workout(int w_id, std::string w_name, int w_price, WorkoutType w_type);
    int getPrice() const;
    // 可以直接用默认拷贝赋值,不需要手动实现
private:
    int price; // 去掉const,对外只通过getPrice()访问保证只读
};

此时原来的排序代码不需要修改就可以正常运行。

方案2:排序时不修改原对象,只排序索引(不需要修改Workout类)

如果要保留price的const属性,可以不对Workout对象本身排序,而是排序其索引,同时还能避免拷贝整个Workout向量、避免你原代码中new vector未delete的内存泄漏问题,效率更高:

std::vector<int> CheapCustomer::order(const std::vector<Workout>& workout_options)
{
    std::vector<int> v;
    // 创建索引数组
    std::vector<int> indices(workout_options.size());
    std::iota(indices.begin(), indices.end(), 0);
    // 按价格排序索引
    std::sort(indices.begin(), indices.end(), [&](int a, int b) {
        return workout_options[a].getPrice() < workout_options[b].getPrice();
    });
    // 按排序后的索引取id
    for (int idx : indices) {
        v.push_back(workout_options[idx].getId());
    }
    return v;
}

方案3:修复unique_ptr版本的写法(和你自己的解决方案一致)

你最终的修改是正确的,核心修正了两个点:

  1. 排序lambda的参数改成引用传递unique_ptr<Workout>& w1,避免拷贝unique_ptr
  2. push_back的时候用std::move把临时unique_ptr转为右值,触发移动构造
    建议进一步优化内存管理,不要用new创建返回的vector,直接返回栈上的vector即可,避免内存泄漏:
std::vector<int> CheapCustomer::order(const std::vector<Workout>& workout_options)
{
    std::vector<int> v; // 直接栈上创建,不需要new
    std::vector<std::unique_ptr<Workout>> v_unique_ptr;
    for (const auto& workout : workout_options) { // 用引用遍历避免拷贝Workout
        v_unique_ptr.push_back(std::make_unique<Workout>(workout.getId(),workout.getName(),workout.getPrice(),workout.getType()));
    }
    std::sort(v_unique_ptr.begin(), v_unique_ptr.end(), [](const std::unique_ptr<Workout>& w1, const std::unique_ptr<Workout>& w2) {
        return w1->getPrice() < w2->getPrice();
    });
    v.push_back(v_unique_ptr[0]->getId());
    return v;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:24:07