Когда используются присваивание и копирующий конструктор

Решение проблемы

В таких классах обязательно нужно предусматривать копирующий деструктор и перегруженную операцию присваивания.

Копирующий конструктор (объявление в определении класса):

. . .

Function(const Function&);

. . .

Копирующий конструктор должен:

- Выделить новую память для создаваемого экземпляра класса,

- Скопировать в нее состояние существующего экземпляра класса.

Реализация:

Function::Function(const Function &f)

{

size = f.size;

xPtr = new float[size];

yPtr = new float[size];

for(int i = 0; i < size; i++){

xPtr[i] = f.xPtr[i];

yPtr[i] = f.yPtr[i];

}

}

Перегруженный оператор присваивания (объявление в определении класса; функция-член класса):

. . .

Function& operator =(const Function&);

. . .

Перегруженный оператор присваивания должен:

- Освободить память, занимаемую экземпляром класса – адресата оператора присваивания (указанного слева от присваивания),

- Выделить новую память для нового значения экземпляра класса – адресата,

- Скопировать в нее значение экземпляра класса, указанного справа от присваивания (параметр оператора присваивания),

- Проверить возможность записи присваивания типа x = x.

Реализация:

Function& Function::operator =(const Function &f)

{

if(this != &f){ // проверка ситуации x = x

;

delete [] xPtr;

delete [] yPtr;

xPtr = yPtr = NULL;

if(size = f.size){ // проверка ситуации, когда у объекта f нет памяти

xPtr = new float[size];

yPtr = new float[size];

for(int i = 0; i < size; i++){

xPtr[i] = f.xPtr[i];

yPtr[i] = f.yPtr[i];

}

}

}

return *this;

}

Перегруженный оператор присваивания работает всегда, когда в программе явно указывается оператор присваивания. Его использование не вызывает затруднений.

Копирующий конструктор работает всегда, когда требуется создать новый экземпляр класса, являющийся копией существующего. Такие ситуации могут возникнуть явно и неявно:

1.Явное создание временных экземпляров класса с использованием копирующего конструктора – при объявлении в программе экземпляров класса с инициализацией их другим экземпляром класса, например:

Function f1(5); // работает инициализирующий конструктор

Function f2(f1), // работает копирующий конструктор

f3 = f1; // работает копирующий конструктор

2.Неявное создание временных экземпляров класса с использованием копирующего конструктора – при использовании функции, аргументами которой являются экземпляры класса (не ссылки и не указатели) и которая возвращает в качестве результата значение экземпляра класса, например:

Function myfunc(Function f)

{

Function tmp;

. . .

return tmp;

}

Если в программе есть такая функция и выполняется действие f1 = myfunc(f2), тогда:

- при вызове функции, т.к. аргументы функции передаются в нее по значению, значение f1 копируется в стек (работает копирующий конструктор);

- когда функция завершает свою работу и выполняет оператор return, значение tmp копируется для замещения вызова функции (опять работает копирующий конструктор);

- параметры функции и объявленная в ней временная переменная tmp разрушаются (работает деструктор);

- и, наконец, работает перегруженный оператор присваивания.