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

如何将不可拷贝对象Base30推入vector?push_back/emplace_back失效解决

让我来帮你分析问题并解决这个困扰:

首先得搞清楚你代码里两种方法失败的原因:

  • push_back(b1) 失败是因为你传入的是左值,push_back 处理左值时会尝试调用拷贝构造函数,但你已经显式 delete 了 Base30 的拷贝构造,自然编译报错。
  • emplace_back(1,2) 看起来应该直接在vector内存里构造对象,但问题出在vector扩容机制上:当vector当前容量不足以容纳新元素时,它会分配更大的内存块,然后把旧内存里的元素转移到新内存。由于你没有给Base30定义移动构造函数,且显式删除拷贝构造后,编译器不会自动生成默认的移动构造,因此vector只能尝试用拷贝构造来转移元素——而拷贝构造是被禁用的,所以报错。

下面是两种可行的解决办法:

方法一:为Base30添加移动构造函数

给Base30加上移动构造,这样vector扩容时可以直接移动元素,emplace_back和push_back(std::move(obj))都能正常工作:

class Base30 { 
public: 
    Base30() = delete; 
    Base30(int a, int b) : a(a), b(b) {} 
    Base30(const Base30& other) = delete; 
    // 添加移动构造函数,noexcept推荐加上,让vector扩容时优先使用移动
    Base30(Base30&& other) noexcept : a(other.a), b(other.b) {} 
    int a; 
    int b; 
}; 

int main() { 
    vector<Base30> vec; 
    // emplace_back 直接在vector内存中构造对象
    vec.emplace_back(1, 2); 
    
    Base30 b1(3, 4);
    // 用std::move把左值转为右值,调用移动构造
    vec.push_back(std::move(b1)); 
    return 0; 
}

方法二:提前给vector预留足够的空间

如果你不想添加移动构造,可以提前用reserve()给vector分配足够的内存,这样vector就不需要触发扩容操作,emplace_back可以直接在已分配的内存里构造对象,完全不需要移动或拷贝元素:

class Base30 { 
public: 
    Base30() = delete; 
    Base30(int a, int b) : a(a), b(b) {} 
    Base30(const Base30& other) = delete; 
    int a; 
    int b; 
}; 

int main() { 
    vector<Base30> vec; 
    // 预留至少1个元素的空间,避免首次添加时扩容
    vec.reserve(1); 
    vec.emplace_back(1, 2); 
    
    // 如果要添加更多元素,提前预留足够的数量
    vec.reserve(vec.size() + 2);
    vec.emplace_back(3, 4);
    vec.emplace_back(5, 6);
    return 0; 
}

这种方法的局限性是你需要提前预估元素数量,否则后续添加元素时还是可能触发扩容,导致失败。

整体来说,优先推荐方法一,移动构造能让vector的使用更灵活,不用再担心扩容的问题。

内容的提问来源于stack exchange,提问作者L.SG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:14:40