为何C++对象内vector成员变量会额外触发一次元素析构?
问题:vector emplace_back后出现额外的对象析构输出
我在使用vector的emplace_back添加元素时,终端输出里出现了额外的"a destory",改用emplace_back后问题依旧。以下是我的代码和输出:
代码实现
a.h
#include <iostream> #include <vector> #include <string> using namespace std; class B { public: string n; B(string name) { this->n = name; cout << this->n<< " create" << endl; } ~B() { cout << this->n << " destory" << endl; } }; class A { public: vector<B> m_B; A():m_B(vector<B>{}) { cout << "class A create" << endl; }; ~A() { cout << "class A destory" << endl; }; };
main.cpp
#include "a.h" void addItem(A& _a,string n) { _a.m_B.emplace_back(n); }; int main() { A a; addItem(a, "a"); addItem(a, "b"); std::cout << a.m_B.size() <<"\n"; std::cout << "Hello World!\n"; }
终端输出
class A create a create b create a destory 2 Hello World! class A destory a destory b destory
我想知道第四行额外出现的“a destory”是何原因?
解答
这个额外的析构输出是vector扩容机制导致的:
- vector初始化时容量为0,第一次调用
emplace_back("a")时,会分配容量为1的内存,构造B对象"a"。 - 第二次调用
emplace_back("b")时,当前vector的容量(1)不足以容纳新元素,因此触发扩容——vector会重新分配一块更大的内存(通常是原容量的2倍,即2)。 - 扩容过程中,原内存里的B对象"a"会被拷贝到新内存区域,随后原内存中的旧"a"对象被销毁,这就是你看到的第四行"a destory"。
- 之后新的B对象"b"在新内存中被构造,输出"b create"。
解决/优化方案
- 提前预留容量:如果提前知道要添加的元素数量,可以调用
vector::reserve()预分配足够的内存,避免扩容。比如在main函数中添加a.m_B.reserve(2);,这样两次emplace_back都不会触发扩容,也就不会出现额外的析构。 - 添加移动构造函数:给B类定义移动构造函数,这样扩容时会移动元素而非拷贝,减少开销(旧元素依然会被析构,但移动操作比拷贝更高效)。示例:
B(B&& other) noexcept : n(std::move(other.n)) { cout << this->n << " move" << endl; }
内容的提问来源于stack exchange,提问作者mikmke
相关产品推荐
相关产品推荐

