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

实现动态数组拷贝构造函数时触发delete_scalar.cpp错误求助

解决DynamicArray类的delete_scalar.cpp内存错误问题

问题根源

  1. 未实现拷贝赋值运算符
    你只定义了拷贝构造函数,但未重载operator=,编译器会生成默认的拷贝赋值运算符,它执行浅拷贝:直接将obj的arr指针值复制给obj2,导致两个对象的arr指向同一块堆内存。程序结束时,两个对象的析构函数会先后调用delete[]释放同一块内存,触发重复释放的内存错误,这就是Visual Studio弹出delete_scalar.cpp错误的核心原因。

  2. 成员函数设计冗余且易出错
    add和print作为类的成员函数,完全不需要传入对象指针,直接访问当前对象的arr、number_of_elements等成员变量即可,当前写法不仅冗余,还容易引发指针误用。

  3. 拷贝构造函数的内存分配偏差
    拷贝构造函数中分配内存时使用other.number_of_elements,但实际应使用other.capacity——数组的容量由capacity定义,如果后续给拷贝出的对象添加元素,会因内存容量不足导致越界。

修复方案

1. 实现拷贝赋值运算符(遵循三法则)

当类包含堆内存指针时,必须自定义拷贝构造函数、拷贝赋值运算符、析构函数(三法则)。实现拷贝赋值时需注意:

  • 先检查自赋值,避免自身赋值导致的内存错误
  • 释放当前对象已占用的内存
  • 分配新内存并拷贝数据
  • 返回当前对象的引用

2. 修正add和print函数

移除不必要的对象指针参数,直接操作当前对象的成员变量。

3. 修正拷贝构造函数的内存分配

将arr(new int[other.number_of_elements])改为arr(new int[other.capacity]),保证拷贝后的对象容量与原对象一致。

修正后的完整代码

DynamicArray.h

#pragma once
class DynamicArray
{
private:
    int* arr;
    int capacity;
    int number_of_elements;
public:
    DynamicArray(int capacity = 1);
    DynamicArray(const DynamicArray&);
    // 添加拷贝赋值运算符声明
    DynamicArray& operator=(const DynamicArray&);
    ~DynamicArray();
    // 修正函数参数
    void add(int value);
    void print();
};

DynamicArray.cpp

#include "DynamicArray.h"
#include <iostream>

DynamicArray::DynamicArray(int capacity) : capacity(capacity), number_of_elements(0), arr(new int[capacity])
{}

DynamicArray::~DynamicArray()
{
    delete[] this->arr;
    this->arr = nullptr;
    this->number_of_elements = 0;
    this->capacity = 0;
}

// 修正拷贝构造函数的内存分配逻辑
DynamicArray::DynamicArray(const DynamicArray& other) : capacity(other.capacity), number_of_elements(other.number_of_elements), arr(new int[other.capacity])
{
    for (int i = 0; i < number_of_elements; i++)
    {
        this->arr[i] = other.arr[i];
    }
}

// 实现拷贝赋值运算符
DynamicArray& DynamicArray::operator=(const DynamicArray& other)
{
    // 检查自赋值
    if (this == &other)
        return *this;

    // 释放当前对象的内存
    delete[] this->arr;

    // 分配新内存并拷贝数据
    this->capacity = other.capacity;
    this->number_of_elements = other.number_of_elements;
    this->arr = new int[this->capacity];
    for (int i = 0; i < this->number_of_elements; i++)
    {
        this->arr[i] = other.arr[i];
    }

    return *this;
}

// 修正add函数:直接操作当前对象,补充扩容逻辑
void DynamicArray::add(int value)
{
    // 处理容量不足的情况,简单扩容为原容量的2倍
    if (number_of_elements >= capacity)
    {
        int* new_arr = new int[capacity * 2];
        for (int i = 0; i < number_of_elements; i++)
        {
            new_arr[i] = arr[i];
        }
        delete[] arr;
        arr = new_arr;
        capacity *= 2;
    }
    arr[number_of_elements++] = value;
}

// 修正print函数:直接操作当前对象
void DynamicArray::print()
{
    for (int i = 0; i < number_of_elements; i++)
    {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

main.cpp

#include "DynamicArray.h"

int main()
{
    DynamicArray obj(5);
    DynamicArray obj2(5);
    obj.add(22);
    obj.add(12);
    obj.add(18);
    obj.add(11);
    obj.print();
    obj2 = obj;
    obj2.print();
}

额外说明

  • 三法则:当类管理堆内存资源时,必须自定义拷贝构造函数、拷贝赋值运算符、析构函数,避免浅拷贝引发的内存泄漏或重复释放问题。
  • 扩容逻辑:原代码未处理容量不足的情况,添加元素超过初始容量时会触发越界错误,修正后的代码补充了基础的扩容逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:25:32