Программирование >>  Расширенная версия языка c++ 

1 ... 45 46 47 [ 48 ] 49 50 51 ... 227


Конструкторы копий никак не влияют на операции присваивания. Ниже показана основная форма конструктора копий:

имя кпзсса (const }1шя г:ласса bobj) { -тг.

вло конструктора , , ,.. ;

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

проблемам.

В основе этих проблем лежит факт создания поразрядной копии объекта.

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

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

а Когда в инструкции объявления объекта один объект используется для

инициализации другого

Когда объект передается в функцию в качестве параметра

Когда в качестве возвращаемого значения функции создается временный

объект

Конструктор копий употребляется только для инициализации, но не для

присваивания.

По умолчанию при инициализации компилятор автоматически генерирует код, осуществляющий поразрядное копирование. (То есть C++ автоматически создает конструктор копий по умолчанию, который просто дублирует

инициализируемый объект.) Однако путем определения конструктора копий

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



1. В данном примере показано, почему необходимо явное определение конструктора копий. В этой программе создается простейший безопасный массив целых, в котором предотвращена возможность нарушения границ массива. Память для массива выделяется с помощью оператора new, а указатель на эту память поддерживается внутри каждого объекта-массива.

/* В этой программе создается класс безопасный массив. Поскольку память для массива выделяется динамически, то, когда один массив используется для инициализации другого, для выделения памяти создается конструктор копий V

#include <iostream> .

#include <cstdlib>

using namespace std;

class array {

int *p; int size; publ i с :

array (int sz) { конструктор

p=new int [sz]; if(!p) exitd);

size=sz;

cout Использование обычного конструктора\n ;

~ {delete [] p;)

конструктор копий - !

arrayjconst array £a) ;

voi{int i, in) { . .

. . if(i>=0 SS, i<size) p[i]=j; - . \ -T

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

myclass у явно инициализирует х

fun ) ; у передается в качестве параметра

y=func2(); у получает возвращаемый объект

В двух первых случаях конструктору копий можно бгло бы передать ссылку на объект у. В последнем случае конструктору копий передается ссылка на объект, возвращаемый функцией iuiic2(,).



152 . Самоучитель C++

in (int i) { ]i ..:,r - :

return p[i]; i r 170 .jo.; *- -

/* Конструктор копий

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

*/

array: ;array(const arra Sa) { tJi v.. .

int i;

size = a. size;

p=ne size] ; выделение памяти для копии

if(!p) exitd);

for(i=0; i<a.size; [i] ; копирование содержимого

cout Использование конструктора копийХп ; . ..

> .! Л- (-.1 г,..£.

int ma in () . . . .

array вызов обычного конструктора

int i ; ,

помещение в массив нескольких значений forU=Li; 1-ч1и; 1-г+) num. put (ir i) ;

вывод на экран массива

ог (i=9; i>=0; - cout num.get(i);

cout \n ;

создание другого массива и инициализация его массивом array вызов конструктора копий

на экран массива х

for cout

return 0;

Когда массив пиш используется для инициализации массива х, вызывается конструктор копий и для нового массива по адресу х.р в]деляется память, а содержимое массива пшп копируется в массив х. В этом случае в массивах х и ПШ11 находятся одинаковые значения, но при этом - это совершенно различные массивы. (Другими словами, указатели х.р и num.p теперь не ссылаются на одну и ту же область памяти.) Если бы не был создан конструктор копий, то поразрядная инициализация при выполнении инструкции array x= пшп привела бы к что массивы х и пшп оказались бы в одной и той же области памяти! (То есть, указатели х.р и num.p ссылались бы на одну и ту же область памяти.)



1 ... 45 46 47 [ 48 ] 49 50 51 ... 227

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика