简体   繁体   English

为什么此模板类无法正常工作?

[英]Why this template class doesn't work properly?

#include <bits/stdc++.h>
using namespace std;


template<class T>
class Array{
public:
Array(int sizeOfArray=1){
    arr = new T[sizeOfArray];
    for(int i=0;i<sizeOfArray;i++){
        arr[i] = 0;
    }
    maxSize = sizeOfArray;
    currentElement = 0;
}

T* growArray(){
    T* newarr = new T[maxSize*2];
    for(int i=0;i<maxSize;i++){
        newarr[i] = arr[i];
        }
    maxSize = maxSize*2;
    return newarr;
}

void add(T element){
    if(currentElement>=maxSize){
        arr = growArray();
    }
    arr[currentElement] = element;
    currentElement++;
}

T get(int index){
    return arr[index];
}

int nrElements(){
    return currentElement;
}

int length(){
    return maxSize;
}

~Array(){
    delete arr;
}
protected:

private:
T* arr;
int maxSize;
int currentElement;
};

template<class T>
Array<T> add(Array<T> &arr1, Array<T> &arr2){
int newsize = arr1.nrElements()+arr2.nrElements()+5;
int aux;
Array<T> arr3(newsize);
for(int i=0;i<arr1.nrElements();i++){
    aux = arr1.get(i);
    arr3.add(aux);
}
for(int i=0;i<arr2.nrElements();i++){
    aux = arr2.get(i);
    arr3.add(aux);
}
return arr3;
}

int main()
{
Array<int> arr(2);
for(int i=0;i<1000;i++){
    arr.add(i);
}

Array<int> arr2(2);
for(int i=1000;i<2000;i++){
    arr2.add(i);
}
Array<int> arr3;
arr3 = add(arr, arr2);
for(int i=0;i<arr3.nrElements();i++){
    cout<<arr3.get(i)<<" ";
}

return 0;
}

The function works properly. 该功能正常工作。 I mean on the line "aux = arr1.get(i);" 我的意思是在“ aux = arr1.get(i);”这一行上 is doing its job but when I try to read the elements of arr3 in main() the first two elements are not 0 and 1. The programs shows instead other big numbers like 175243462 and 152614213. 正在执行其工作,但是当我尝试读取main()中arr3的元素时,前两个元素不是0和1。程序显示了其他大数字,例如175243462和152614213。

OP's reported bug is likely the result of a Rule of Three violation. OP报告的错误很可能是违反三规则的结果。 What is The Rule of Three? 什么是三法则?

template<class T>
Array<T> add(Array<T> &arr1, Array<T> &arr2)
{
    int newsize = arr1.nrElements() + arr2.nrElements() + 5;
    int aux;
    Array<T> arr3(newsize); <<- made a local array
    for (int i = 0; i < arr1.nrElements(); i++)
    {
        aux = arr1.get(i);
        arr3.add(aux);
    }
    for (int i = 0; i < arr2.nrElements(); i++)
    {
        aux = arr2.get(i);
        arr3.add(aux);
    }
    return arr3; <<- return by value. May trigger a copy of arr3, then destroy arr3
}

There is no copy constructor or assignment operator, so the compiler generate default methods that are... Pretty simple. 没有复制构造函数或赋值运算符,因此编译器生成的默认方法非常简单。 They blindly invoke the copy and assignment operator of their member variables, and the default copy behavior of a pointer is to copy the memory location and not the memory pointed at. 他们盲目地调用其成员变量的复制和赋值运算符,并且指针的默认复制行为是复制内存位置而不是指向的内存。 This means the copies and the source's arr member all point at the same memory location. 这意味着副本和源的arr成员都指向同一存储位置。 The Array destructor delete arr; Array析构函数delete arr; , so the copies now are left pointing to freed memory. ,因此副本现在指向已释放的内存。 Accessing any of the copies is now undefined behaviour, and destroying any of the copies will cause a double delete. 现在,访问任何副本都是未定义的行为,销毁任何副本将导致重复删除。 Very bad scene. 非常糟糕的一幕。

Solution, to this bug anyway, Implement copy constructor and assignment operator. 解决方案,无论如何要解决此错误,请实现复制构造函数和赋值运算符。 Here is some help on that: Operator overloading 这方面有一些帮助: 运算符重载

Bonus bug: 奖励错误:

void add(T element)
{
    if (currentElement >= maxSize)
    {
        arr = growArray(); <<- did not release the old array pointed at by arr
    }
    arr[currentElement] = element;
    currentElement++;
}

add leaks memory because it does not delete arr before replacing arr This is more difficult to do in add (admittedly not by much) than it is in growArray so, add泄漏内存,因为它不会delete arr更换前arr这是比较难做到add (不是很多不可否认),比它在growArray如此,

void growArray() <<- returns nothing
{
    T* newarr = new T[maxSize * 2];
    for (int i = 0; i < maxSize; i++)
    {
        newarr[i] = arr[i];
    }
    maxSize = maxSize * 2;
    delete arr; <<- clean up old arr
    arr = newarr; <<- assign arr here
}

and

void add(T element)
{
    if (currentElement >= maxSize)
    {
        growArray(); <<- everything done by growArray
    }
    arr[currentElement] = element;
    currentElement++;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM