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

为何调用vec.push_back(v)时会触发析构函数?

仿STL Vector嵌套push_back后元素被销毁的问题分析与修复

你的Vector类存在几个核心问题,直接导致了嵌套push_back后元素被销毁的现象,下面逐个拆解并给出修复方案:

核心问题1:缺失深拷贝的拷贝构造与赋值运算符

C++编译器会为类生成默认的拷贝构造函数和赋值运算符,但这些默认实现是浅拷贝——只复制成员变量的表面值,比如你的arr指针。当你调用vec.push_back(v)时:

  • 如果你用的是传值的push_back(Vector val)重载,参数val是v的浅拷贝副本,它和v共享同一块arr内存。
  • 函数执行完毕后,临时参数val会被析构,调用~Vector()释放arr内存,此时原v的arr就变成了野指针,后续访问就会表现为"元素被销毁"。
  • 即使你用引用版本的push_back,当Vector内部Realloc扩容时,循环里的arr[i] = temp[i]也是浅拷贝,会导致多个Vector对象共享内存,析构时重复释放。

核心问题2:冗余的push_back重载

你额外写了push_back(Vector val)的重载,完全没必要——模板类的T已经可以处理Vector<int>类型,这个重载反而强制传值,引发不必要的拷贝和临时对象析构,加重了问题。

其他次要问题

  • isEmpty逻辑错误:if(capacity && size)会在size为0(已有一个元素)时返回true,判断为空,明显不符合预期。
  • 析构函数输出误导:打印的是capacity却标注为"size",容易混淆调试信息。
  • at函数返回0不合理:对于非数值类型,返回0会编译错误,应该返回T{}默认构造值。

修复后的完整代码

#include <iostream>
using namespace std;

template <typename T, int cap=1>
class Vector {
private:
    T* arr{};
    int capacity = cap;
    int size = -1; // size表示最后一个元素的索引,sizeOf()返回元素总数size+1

public:
    // 默认构造函数
    Vector() {
        arr = new T[capacity]{};
    }

    // 拷贝构造:深拷贝,确保每个Vector拥有独立内存
    Vector(const Vector& other) {
        capacity = other.capacity;
        size = other.size;
        arr = new T[capacity]{};
        for (int i = 0; i <= size; ++i) {
            arr[i] = other.arr[i];
        }
    }

    // 赋值运算符:用拷贝交换范式实现深拷贝,简洁且安全
    Vector& operator=(Vector other) {
        swap(arr, other.arr);
        swap(capacity, other.capacity);
        swap(size, other.size);
        return *this;
    }

    // 析构函数:释放内存并标记指针为空
    ~Vector() {
        cout << "Deleting Vector | capacity: " << capacity << ", element count: " << sizeOf() << '\n';
        delete[] arr;
        arr = nullptr;
    }

    // 判断是否为空的正确逻辑
    bool isEmpty() const {
        return size == -1;
    }

    // 扩容函数:深拷贝原元素到新内存
    void Realloc() {
        cout << "Realloc: capacity from " << capacity << " → " << 2*capacity << '\n';
        T* temp = arr;
        capacity *= 2;
        arr = new T[capacity]{};

        for (int i = 0; i <= size; ++i) {
            arr[i] = temp[i]; // 调用T的赋值运算符,嵌套时自动深拷贝
        }

        delete[] temp;
        temp = nullptr;
    }

    // 返回元素总数
    int sizeOf() const {
        return size + 1;
    }

    // 统一的push_back:用const引用避免不必要拷贝,支持临时对象
    void push_back(const T& val) {
        ++size;
        if (size < capacity) {
            arr[size] = val;
            return;
        }
        Realloc();
        arr[size] = val;
    }

    // 删除指定位置元素
    void erase(int pointer) {
        if (pointer < 0 || pointer > size) {
            return;
        }

        for (; pointer < size; ++pointer) {
            arr[pointer] = arr[pointer + 1];
        }
        --size;
    }

    // 返回当前容量
    int capacityOf() const {
        return capacity;
    }

    // 安全访问元素,越界返回默认值
    T at(int val) const {
        if (val >= 0 && val <= size) {
            return arr[val];
        }
        return T{};
    }

    // 非const下标访问
    T& operator[] (int val) {
        return arr[val];
    }

    // const下标访问,支持const对象
    const T& operator[] (int val) const {
        return arr[val];
    }
};

测试用main函数

int main()
{
    Vector<int> v;
    Vector<Vector<int>> vec;

    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    v.push_back(6);
    cout << "v's element count: " << v.sizeOf() << "\n";
    
    vec.push_back(v);
    // 验证嵌套Vector的元素未被销毁
    cout << "\nNested vector element count: " << vec[0].sizeOf() << "\n";
    cout << "First element of nested vector: " << vec[0][0] << "\n";
    cout << "Last element of nested vector: " << vec[0][5] << "\n";
}

修复关键点说明

  1. 深拷贝实现:拷贝构造和赋值运算符确保每个Vector对象拥有独立的内存空间,拷贝时复制所有元素,彻底避免浅拷贝导致的内存共享问题。
  2. 统一push_back:删除冗余重载,改用const T&参数,既避免不必要的拷贝,又支持传入临时对象。
  3. 扩容逻辑优化:Realloc中的拷贝操作现在会调用T的赋值运算符,对于嵌套的Vector来说,自动执行深拷贝。
  4. 逻辑修正:修复isEmpty、析构函数输出等细节问题,提升代码的正确性和可调试性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:00:48