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

为何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扩容机制导致的:

  1. vector初始化时容量为0,第一次调用emplace_back("a")时,会分配容量为1的内存,构造B对象"a"。
  2. 第二次调用emplace_back("b")时,当前vector的容量(1)不足以容纳新元素,因此触发扩容——vector会重新分配一块更大的内存(通常是原容量的2倍,即2)。
  3. 扩容过程中,原内存里的B对象"a"会被拷贝到新内存区域,随后原内存中的旧"a"对象被销毁,这就是你看到的第四行"a destory"。
  4. 之后新的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:31:09