调用std::vector::pop_back()后析构函数被调用两次的原因及相关疑问
C++ vector操作与对象析构疑问解答
代码示例
#include <iostream> #include <vector> using namespace std; class A { public: A() { cout << "Constructor called" << endl; } ~A() { cout << "Destructor called: " << this << endl; } }; int main() { A a, aa; std::vector<A> arr; arr.push_back(a); arr.push_back(aa); arr.pop_back(); cout << "finish" << endl; }
运行输出
Constructor called Constructor called Destructor called: 0x561568fa92c0 Destructor called: 0x561568fa92e4 finish Destructor called: 0x561568fa92e0 Destructor called: 0x7ffe51288a4c Destructor called: 0x7ffe51288a48
疑问解答
1. 为何调用std::vector::pop_back()后析构函数会被调用两次?
这是vector扩容机制导致的:
- 第一次
push_back(a)时,vector分配了能容纳1个元素的内存; - 第二次
push_back(aa)时,原内存空间不足,vector会重新分配一块更大的内存,把旧内存里的a的副本拷贝到新内存,随后销毁旧内存中的这个副本——这是第一次析构; - 调用
pop_back()时,会销毁vector中最后一个元素(也就是aa的副本)——这是第二次析构。
所以在finish打印前会看到两次析构调用。
2. 在打印"finish"之前被销毁的是哪些对象?
- 第一个被销毁的是**
vector扩容时旧内存里的a的副本**(对应地址0x561568fa92c0); - 第二个被销毁的是**
pop_back()移除的aa的副本**(对应地址0x561568fa92e4)。
这两个都是vector内部存储的拷贝,不是main函数里直接定义的a和aa。
3. std::vector::push_back()是否会创建传入对象的副本?
是的,push_back()一定会创建传入对象的副本。vector内部存储的是对象的拷贝,而非原对象的引用或指针。你可以给类A添加拷贝构造函数验证:
A(const A& other) { cout << "Copy constructor called: " << &other << " -> " << this << endl; }
添加后运行代码,会看到每次push_back都会触发拷贝构造函数,直接证明副本的创建过程。
内容的提问来源于stack exchange,提问作者Game Code
相关产品推荐
相关产品推荐

