Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
369164_46F07_otvety_na_bilety_po_oop_si.doc
Скачиваний:
44
Добавлен:
24.12.2018
Размер:
613.38 Кб
Скачать

29. Излишнее копирование. Конструктор копии. Операции присваивания.

1. Излишнее копирование

При выполнении любой бинарной операции для типа complex реализующей эту операцию функции будут передаваться как параметры копии обоих операндов. Дополнительные расходы, вызванные копированием двух значений типа double, заметны, хотя по всей видимости допустимы. К сожалению представление не всех классов является столь удобно компактным. Чтобы избежать избыточного копирования, можно определять функции с параметрами типа ссылки:

class matrix {

double m[4][4];

public:

matrix();

friend matrix operator+(const matrix&, const matrix&);

friend matrix operator*(const matrix&, const matrix&);

};

Ссылки позволяют без излишнего копирования использовать выражения с обычными арифметическими операциями и для больших объектов. Указатели для этой цели использовать нельзя, т.к. невозможно переопределить интерпретацию операции, если она применяется к указателю.

Это допустимо, но возникает проблема с выделением памяти. Поскольку ссылка на результат операции будет передаваться как ссылка на возвращаемое функцией значение, оно не может быть автоматической переменной этой функции. Поскольку операция может использоваться неоднократно в одном выражении, результат не может быть и локальной статической переменной. Как правило, результат будет записываться в отведенный в свободной памяти объект. Обычно бывает дешевле (по затратам на время выполнения и память данных и команд) копировать результирующее значение, чем размещать его в свободной памяти и затем в конечном счете освобождать выделенную память. К тому же этот способ проще запрограммировать.

2. Конструктор копирования

Как правило, при создании объекта вызывается конструктор, за исключением случая, когда объект создается как копия другого объекта этого же класса, например:

date date2 = date1;

Однако имеются случаи, в которых создание объекта без вызова конструктора осуществляется неявно:

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

- результат функции - объект, передаваемый по значению, в момент выполнения оператора return копируется во временный объект, сохраняющий результат функции.

Во всех этих случаях транслятор не вызывает конструктора для вновь создаваемого объекта:

- dat2 в приведенном определении;

- создаваемого в стеке формального параметра;

- временного объекта, сохраняющего значение, возвращаемое функцией.

Вместо этого в них копируется содержимое объекта-источника:

- dat1 в приведенном примере;

- фактического параметра;

- объекта - результата в операторе return.

При наличии в объекте указателей на динамические переменные и массивы или идентификаторов связанных ресурсов, такое копирование требует дублирования этих переменных или ресурсов в объекте-приемнике, как это было сделано выше в операции присваивания. С этой целью вводится конструктор копирования, который автоматически вызывается во всех перечисленных случаях. Он имеет единственный параметр - ссылку на объект-источник:

class string

{

char *Str;

int size;

public:

string(string&); // Конструктор копирования

};

string::string(string& right) // Создает копии динамических

{ // переменных и ресурсов

s = new char[right->size];

strcpy(Str,right->Str);

}

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]