动态数组类 c++

Dynamic array class c++

本文关键字:c++ 数组 动态      更新时间:2023-10-16

我正在编写一个动态数组类。我包含一个复制构造函数和 operator= 函数,以允许我将一个数组分配给另一个数组。当我将相同长度的数组分配给彼此时,它有效,但是当它们具有不同的长度时,我会收到编译器内存警告和/或代码炸弹而不执行,具体取决于左侧数组是否大于右侧数组,反之亦然。我有一个将值插入数组的函数,并认为问题可能出在这里(注意:我不得不注释掉析构函数中的内存删除以使代码运行)。

class Array
{
    private:
    int * ptr;
    int size; 
    int numElement;
public:
    Array();
    Array(const int*, int);
    Array(const Array&);
    ~Array();
    void setValueAtIndex(int, int);
    void insertValueAtEnd(int ); 
    int getArraySize();
    const Array& operator=(const Array& );  
};
#include "array.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
Array::Array()
{
  size = 10;
  numElement = 0;
  ptr = new int[size];
  for (int i = 0; i < size; ++i)
  {
    ptr[i] = 0;
  }
}
Array::Array(const int * ptr_, int size_)
{
  size = size_;
  numElement = size;
  ptr = new int[numElement];
  for (int i = 0; i < size; ++i)
  {
    ptr[i] = ptr_[i];
  }
}
Array::Array(const Array& other)
{
  size = other.size;
  numElement = other.numElement;
  if (other.ptr)
  {    
      ptr = new int[numElement];
      for(int i = 0; i < size; ++i)
      {
        ptr[i] = other.ptr[i];
      }
      if(!ptr)
      {
        exit(EXIT_FAILURE);
      }
  }
  else ptr = 0;
}
Array::~Array()
{
  if(ptr)
  {
   //delete [] ptr;
   //ptr = 0;
  }
}
void Array::setValueAtIndex(int a, int b)
{
  if(b > size)
  {  
      exit(EXIT_FAILURE);
  }
  ptr[b] = a;
}
void Array::insertValueAtEnd(int insert)
{
  if(numElement == size)
  {
      size++;
  } 
  ptr[size-1] = insert;
  numElement++;
}
int Array::getArraySize()
{
  return size;
}
const Array& Array::operator=(const Array& other)
{    
    if(this != &other)
    {
     if (ptr)
     {
       delete [] ptr;
      ptr = 0;
     }
     numElement = other.numElement;
     size = other.size;
     if(other.ptr)
     {
       ptr = new int[numElement];
       for(int i = 0; i < size; ++i)
       {
         ptr[i] = other.ptr[i]; 
       }
     }
     else ptr = 0;
    }
    return *this;
}

您的代码存在多个问题!从复制构造函数中的次要开始:如果new T[n]失败,则返回0。相反,它会引发和异常。因此,您的测试if (!ptr)将永远不会达到。在您的代码中,无论如何都为时已晚,因为您已经使用了指针!

赋值运算符完全乱码!使用自赋值检查通常是一个很好的指示,表明代码不是异常安全的(如果没有此检查,自赋值真的不起作用),或者你正在针对极少数情况进行优化(希望你不会更频繁地将对象分配给自己而不是分配给其他对象)。在您的情况下,检查表明代码如果正常工作,则不会异常安全:您开始删除内存,如果分配内存失败并抛出,则无法恢复内存。可能引起您悲伤的主要错误是你分配了numElements对象(这似乎是数组中的元素数量,而不是它的容量),但你复制了size对象(这似乎是可能可用的元素的数量,即numElements < size)。作为旁注,我强烈建议您使用与标准C++库对其容器相同的名称,即size()实际元素的数量和capacity()保留空间的元素数量。

综上所述,实现赋值运算符的最佳方法是利用已经为复制构造函数和析构函数完成的工作:它们已经知道如何复制对象以及如何摆脱对象。执行此操作的方法如下所示:

Array& Array::operator= (Array other) {
    this->swap(other);
    return *this;
}
void Array::swap(Array& other) {
     std::swap(this->ptr, other.ptr);
     std::swap(this->size, other.size);
     std::swap(this->numElements, other.numElements);
}

此方法还要求还有一个函数swap()可以交换该类型的两个对象。但是,编写通常是微不足道的:您只需std::swap()每个成员。

您的代码使用 insertValueAtEnd() 时会中断,因为它不会增加底层数组的大小。 它通过这个简单的测试用例为我崩溃了:

int realarr[] = { 1,2,3};
Array arr1(realarr, 3);
arr1.insertValueAtEnd(7);

您需要检查是否已达到容量(您称之为大小),如果是,则需要增加基础存储。

我假设您正在实现一个动态数组?

只是一个风格问题,如果你愿意,你可以忽略。 更常见的是将 name_ 用作类数据成员并将 name 作为参数传递。