Оператор присваивания вылетает код, пока я делаю шаблон класса - PullRequest
0 голосов
/ 01 октября 2019

Я делаю шаблон для векторного класса, в котором я делаю вектор из массива. Но внутри класса оператор присваивания вызывает сбой кода, так как я вижу, что возвращаемое значение несколько (процесс вернул -1073741819 (0xC0000005)).

int i=0;
const int size = 4;
template<class T>
class vector{
public:
    vector()
    {
        x = new T[size];
       for(i=0;i<size;i++)
            x[i] =0 ;
    }
    vector( T *a)   // This part is creating issue if i comment it out code 
// successfully return with value Zero. But with this it doesn't work at all.
    {
      //  cout<<"called";
        for(i=0;i<size;i++)
        {
            x[i] = a[i];
        }
    }
    T  operator *(vector &y)
    {
        T sum = 0;
        for(i=0;i<size;i++)
        {
            sum += this->x[i] + y.x[i];
        }
        return sum;
    }

private:
    T * x; // Type of vector;

};
int main()
{
    int arr1[4] = {2,3,4,5};
    int arr2[4] = {6,7,8,9};
    vector<int> v1;
    vector<int>v2;
    v1 = arr1;  // This call is the culprit. it doesn't work t all.
    v2 = arr2;

    return 0;
}```

1 Ответ

4 голосов
/ 01 октября 2019

У вас есть несколько проблем, которые приводят к сбою и другим проблемам.

Во-первых, утверждение

v1 = arr1;

эквивалентно

v1 = vector<int>(&arr1[0]);

Этоозначает, что будет создан временный объект vector<int>, который вызывает конструктор vector(T *a).

И здесь начинаются проблемы: поскольку это конструктор, конструируемый объект является неинициализированным , так какцель конструктора - инициализировать его. Это означает, что переменная-член x будет также неинициализирована и не будет указывать на правильное местоположение.

Вам нужно выделить память и заставить x указывать на эту память, в противном случаевы разыменовываете неинициализированный указатель, который приводит к неопределенному поведению и очень вероятно к вашему падению.


Что касается других проблем, в первую очередь вы упускаете деструктор, что означает, что выделение памятине нужно нигде быть свободнымЧто в данном случае на самом деле хорошо, потому что у вас нет действительного оператора присваивания (и вы полагаетесь на оператор присваивания, сгенерированный компилятором), копирование в v1 = arr1 будет мелкой копией, которая копирует только сам указатель, а непамять, на которую он указывает.

Проблема поверхностного копирования означает, что некоторое время у вас будет два объекта, элемент x которых будет указывать на одну и ту же память. И если один объект удаляет эту память (например, когда упомянутый выше временный объект разрушен), то второй указатель в v1 больше не будет действительным.

Это причина правил трехи пять .

...