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

调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:42:43