如何将不可拷贝对象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
相关产品推荐
相关产品推荐

