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

std::vector析构函数调用机制及类型区分逻辑探究

std::vector析构函数调用逻辑解析

核心疑问

在实现std::vector时,对其隐式调用析构函数的逻辑存在困惑。std::vector的元素可能涵盖以下类型:

  • 类对象(T)
  • 指向类对象的普通指针/智能指针(T*、shared_ptr)
  • 内置类型(int)
  • 指向内置类型的指针(int*)

调用resize()、reserve()、erase()或pop_back()等方法时,可能触发析构函数调用。需要明确:std::vector是如何处理析构函数调用的?是否会通过区分元素类型来决定是否调用?

验证实验

示例1:元素为类对象

#include <vector>
#include <iostream>
using namespace std;

struct Tmp {
    ~Tmp() { cerr << "析构函数已调用。" << endl; }
};

int main (void)
{
    std::vector<Tmp>arr;
    Tmp tmp = Tmp();
    cerr << "容量:" << arr.capacity() << endl;//0
    arr.push_back (tmp);
    cerr << "容量:" << arr.capacity() << endl;//1
    arr.push_back (tmp);
    cerr << "容量:" << arr.capacity() << endl;//2
    cerr << "pop_back开始------------" << std::endl;
    arr.pop_back();
    arr.pop_back();
    cerr << "pop_back结束--------------" << endl;
}

输出结果:

容量:0
容量:1
析构函数已调用。
容量:2
pop_back开始------------
析构函数已调用。
析构函数已调用。
pop_back结束--------------
析构函数已调用。

示例2:元素为指向类对象的内置指针

修改元素类型为Tmp*后的核心代码:

...
std::vector<Tmp*>arr;
Tmp * tmp = new Tmp;
...

输出结果:

容量:0
容量:1
容量:2
pop_back开始------------
pop_back结束--------------

可见Tmp的析构函数不会被自动调用。

示例3:元素为shared_ptr

核心代码修改为:

std::vector<shared_ptr<Tmp>>arr;
auto tmp = make_shared<Tmp>();

... //复制后引用计数应为3
tmp = nullptr; //引用计数减1

cerr << "pop_back开始------------" << std::endl;
arr.pop_back();//引用计数减1
arr.pop_back();//引用计数减1
cerr << "pop_back结束--------------" << endl;

输出结果:

容量:0
容量:1
容量:2
pop_back开始------------
析构函数已调用。
pop_back结束--------------

shared_ptr的析构函数会被调用,当引用计数降至0时,Tmp的析构函数会被触发。

原理解析

std::vector不会主动区分元素类型,它的核心逻辑是:对每个被移除的元素,都会调用该元素类型的析构函数。

  • 对于类对象(如示例1的Tmp):元素本身是对象,移除时直接调用Tmp的析构函数,因此能看到对应输出。
  • 对于内置指针(如示例2的Tmp*):指针属于内置类型,其析构函数是编译器默认生成的空操作,调用指针的析构不会触发指向对象的析构,这也是手动分配内存时易出现泄漏的原因。
  • 对于shared_ptr<T>(示例3):shared_ptr是类模板,它的析构函数会自动管理引用计数,当计数归0时自动调用指向对象的析构函数,因此最终能看到Tmp的析构输出。
  • 对于内置类型(如int):调用默认的空析构操作,无任何可见行为。
  • 对于指向内置类型的指针(如int*):和Tmp*逻辑一致,仅销毁指针本身,不会释放指向的内存,需手动处理。

简言之,std::vector只负责销毁它直接存储的元素:

  • 存储对象时,销毁对象;
  • 存储指针时,销毁指针(不销毁指针指向的内容);
  • 存储智能指针时,销毁智能指针(智能指针自身负责销毁指向的内容)。

内容的提问来源于stack exchange,提问作者sixsixqaq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:35:27