【问题标题】:Dynamic array class c++动态数组类 c++
【发布时间】:2013-09-15 11:33:00
【问题描述】:

我正在编写一个动态数组类。我包含了一个复制构造函数和 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;
}

【问题讨论】:

  • 您的复制构造函数有一些问题。您正在分配numElement,但复制循环使用size。此外,如果数组已分配,则存在泄漏。
  • 什么测试用例导致崩溃?
  • 请分享主要的,我无法粉碎它,但它可能是我不明白的东西

标签: c++ dynamic-arrays


【解决方案1】:

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

赋值运算符完全是乱码!使用自赋值检查通常很好地表明代码不是异常安全的(如果没有此检查自赋值真的无法工作)或者您正在针对罕见情况进行优化(希望您没有将对象分配给自己而不是分配给其他对象)。在您的情况下,检查表明代码(如果它正在运行)将不是异常安全的:您开始删除如果分配内存失败并抛出,您将无法取回的内存。可能导致您悲伤的主要错误是您分配了 numElements 对象(这似乎是数组中的元素数量,而不是其容量)但您复制了 size 对象(这似乎是可能可用元素的数量,即numElements &lt; 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()每个成员。

【讨论】:

  • 函数swap如何处理分配的内存?
  • @BlackMamba:它不需要搞乱内存分配:它只是在两个不同对象之间交换所有成员,即,它只是将分配的内存从一个对象转移到另一个对象。这种转移唯一一次不起作用是分配使用不同的有状态分配器,但在Array中分配内存的方式并非如此。
【解决方案2】:

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

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

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

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

只是一个样式问题,如果您愿意,可以忽略。更常见的是使用name_作为类数据成员,将name作为参数传入。

【讨论】:

    猜你喜欢
    • 2020-07-22
    • 2012-06-19
    • 2018-09-11
    • 1970-01-01
    • 2018-01-13
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多