扩展/缩小动态数组

时间:2014-02-18 00:47:45

标签: c++ dynamic-arrays

我有一个创建模板容器类的赋值,该类具有可以增加和减少的动态数组。当显示数组时,对于数组中扩展它的元素,我得到垃圾数字或根本没有数字(因此如果它在第五个元素上展开,则在我输入第六个元素后,该值将变为垃圾)。当我尝试删除元素时,我收到Debug Assertion Failed错误。

这是我的代码:

template <class T> class container {
public:
   container(); // constructor
   // Post-condition: count is set to -1 and dynamic array size set to 5
   ~container(); //destructor
   void insert(T &n);
   //  Pre-condition: a value is passed to the function 
   // Post-condition: if data array is not full, increment count by 1 and insert the value in the array 
   // Otherwise, display "Container full! No insertion is made."            
   void remove();
   //Post-condition: if data array is not empty, remove the data[count] element in data array and decrement count by 1; 
   //otherwise, display a message "Container empty! Nothing is removed from it."    
   void display();
   // Post-condition: if the array is not empty, displays all values in data array similar to the sample output;
   //Otherwise, display the message “Container is now empty!"
   void fillarray(container c);
   //pre-condition: a container c is passed to the function
   //post-condition: dynamic array of chosen type is created and filled continuously with user entered values
private:
   bool empty;
   //Post-condition: returns true is the array is empty, otherwise returns false
   T *data; // dynamically allocated array used to store or contain the inserted values
   int count;   // indicates how many values have been inserted
   int max;
};
template <class T> container<T>::container()
{
   count = -1;
   max = 5;
   data = new T[max];
   assert(data != NULL);
}
template <class T> container<T>::~container()
{
   delete [] data;
}
template <class T> void container<T>::insert(T &n)
{
   if (count >= (max - 1))
   {
      max = max * 2;
      cout << "\nContainer full! Array size is increased by " << max/2  << ".";
      T *temp = new T[max];
      assert(temp != NULL);
      for (int i = 0; i < count; i++)
         temp[i] = data[i];
      delete [] data;
      data = temp;
      count++;
      data[count] = n;
   }
   else
      count++;
   data[count] = n;
}
template <class T> void container<T>::remove()
{
   empty = count < 0;
   if (empty == 1)
   {
      cout << "\nContainer empty! Nothing is removed from it.";}
   else
   {
      count--;
      T *temp1 = new T[max];
      assert(temp1 != NULL);
      for (int i = 0; i < count; i++)
         temp1[i] = data[i];
      delete [] data;
      data = temp1;
   }
}
template <class T> void container<T>::display()
{
   empty = count < 0;
   if (empty == 1)
   {
      cout << "\nContainer is now empty!";}
   else
   {
      for (int i = 0; i <= count; ++i)
         cout << " " << data[i];
   }
}
template <class T> void container<T>::fillarray(container c)
{
   char ans;
   do
   {
      T value;
      cout << "\nEnter a value:";
      cin >> value;
      c.insert(value);
      cout << "\nAfter inserting, the \"container\" contains:" << endl;
      c.display();
      cout << "\nEnter more? (Y/y or N/n)";
      cin >> ans;
   } while (ans == 'Y' || ans == 'y');
   for (int i = 0; i <= count; i++) 
   {
      c.remove();
      cout << "\nAfter removing a value from it, the \"container\" contains:" << endl;
      c.display();
      cout << endl;
   }
}
// The main driver function to be used to test implementation
int main()
{
   char choice;
   cout << "\nEnter S for string container, D for double";
   cin >> choice;
   if (choice == 'S' || choice == 's')
   {
      container<string> c;
      c.display();
      c.fillarray(c);
   }
   else if(choice == 'D' || choice == 'd')
   {
      container<double> c;
      c.display();
      c.fillarray(c);
   }
   return 0;
}

2 个答案:

答案 0 :(得分:2)

template <class T> void container<T>::fillarray(container c)
{
    //...
}

此功能实际上涉及两个container<T>个对象:*thisc

由于您“按值传递”(函数参数不是参考),c中的fillarray被创建为c中原始main的副本。在fillarray中修改c,删除和更改c.data,但this->data仍包含指向原始存储的悬空指针。不久之后,你会得到不确定的行为;幸运的是,发生了很多坏事,你可以说出错了。

根据Rule of Three (Plus Two),如果类有析构函数,您可能不应该允许编译器生成默认的复制构造函数和复制赋值,您可能需要考虑实现移动构造函数并移动赋值。 / p>

满足该规则的最简单,有时最好的方法是禁用复制:

template <class T> class container
{
public:
    container(container const&) = delete;
    container& operator=(container const&) = delete;
    //...
};

然后编译器会确保你不小心制作副本并让自己陷入这种麻烦。

答案 1 :(得分:0)

通过引用最大索引而不是条目数来使生活变得混乱。但是,使用您的方案,插入中的这一行是奇数:

  for (int i = 0; i < count; i++)

因为这不会复制最终条目。