2012-04-05 2 views
2

Я пишу общий класс Array и операторы перегрузки для удобства. Я получил объект Array <> объект для хранения других объектов Array <>, но у меня возникли проблемы с переопределением оператора *. Мне нужно скопировать левый объект, так что мой оператор * Код такой:C++ Template Copy Constructor Deep Copy

Array<T>& operator*(const double scalar) { 
    return Array<T>(*this) *= scalar; 
} 

(оператор * = перегружен и работает).

Я отменяют конструктор копирования, как показано ниже:

UPDATE: Новый конструктор копирования:

Array<T> (const Array<T>& copyfrom) { 
    size_=copyfrom.size(); 
    data=new T[size_]; 
    copy(&copyfrom.data[0], &copyfrom.data[size_], data); 
} 

Моя мысль в том, что если массив не общий, но всегда заполнены примитивным, этот код будет работать , Но я думаю, что здесь что-то происходит, потому что я использую шаблон, который вызывает поведение, которого я не ожидаю. Массив данных в новом массиве «с глубоким копированием» действует так, как будто это всего лишь мелкая копия указателя массива данных «copyfrom».

Как сделать этот конструктор экземпляра работы как для примитивов, так и для объектов, используя шаблоны? Или, еще лучше, есть ли способ перегрузить оператор *, не беспокоясь о конструкторах копирования? Благодарю.

EDIT: Код для operator*=. Тем не менее, я все еще думаю, что моя проблема заключается в использовании конструктора копирования.

Array<T>& operator*=(const double scalar) { 
    for (int i=0; i<size_; i++) 
     data[i]*=scalar; 
    return *this; 
} 

EDIT: я понял, что я получаю проблемы, потому что я игнорировал size моих внутренних массивы в моем массиве массивов. Теперь все надежнее. Все были очень полезны, и я думаю, что я на пути к этой работе. Мой operator= (который я не перегрузил, хороший улов, Майкл) теперь, как показано ниже. Он действует как ожидалось, но я начинаю получать ошибки malloc в своей программе, и я изучаю почему. Что-то не так с управлением памятью здесь?

Array<T>& operator=(const Array<T>& a) { 
    if (this==&a) 
     return *this; 
    delete [] data; 

    size_=a.size(); 
    data=new T(size_); 
    copy(&a.data[0], &a.data[a.size()], data); 

    return *this; 
} 

EDIT: Я исправил ошибки malloc! Сейчас мои методы работают так, как планировалось. Проблемы с памятью приходили, потому что у меня был этот заголовок метода:

template <typename T> 
static Array<T> matrixSolve (Array<Array<T> > m); 

Я принимал массив массивов по значению. Всевозможные проблемы. Взял массив по ссылке и все получилось. Спасибо всем за помощь!

+0

@MichaelAnderson Код 'operator *' не должен возвращать 'this'. Вызов 'Array (* this)' вызывает конструктор копирования, который я подтвердил. Кроме того, я не получаю ошибку компиляции, когда я использую 'operator * =', если я создаю 'operator *' const, поэтому я не должен мутировать 'this'. – Enigmoid

+0

Вы верны - я удалю эти комментарии. –

+0

Можете ли вы показать нам 'Array :: operator ='? Когда вы используете 'data [i] = copyfrom.data [i]', вы вызываете 'operator =' для данных. Если они не определены, вы получите значение по умолчанию. Итак, если у вас гнездятся массивы и массивы, то не будет = тогда будут плохие вещи. –

ответ

3

Вы хотите, чтобы ваш оператор * функцию чтобы выглядеть следующим образом:

Array<T> operator*(const double scalar) const { 
    Array<T> result(*this); 
    result *= scalar; 
    return result; 
} 

Если вы возвращаете Array<T> &, то вы будете возвращать ссылку на временный, который будет уничтожен, в результате чего неопределенное поведение ,

+0

Возможно, вы захотите сделать этот 'operator *' const тоже. –

+0

@MichaelAnderson: true - изменено –

+0

Нет ничего плохого в том, чтобы сблизить эти три строки с одним, как в исходном коде OP; на самом деле я считаю его более читаемым, потому что вы не вводите шум объявления временного имени переменной, и сразу видно, что вы по существу выполняете «' * this * = scalar' с резервной копией ». Это была просто обратная ссылка и отсутствующая 'const', которая была неправильной. – leftaroundabout