|
Программирование >> Аргументация конструирования
Ресурсом, требующим глубокого копирования, является не только память в куче, но и открытые файлы, порты, выделенные аппаратные средства (например, принтеры) и т.п. Кроме того, все эти типы ресурсов должны освобождаться деструктором. Таким образом, можно вывести правило: глубокое копирование необходимо всегда, когда деструктор класса освобождает ресурсы. Копии создаются не только тогда, когда объекты передаются в функции по значению. Копии объектов могут создаваться и по другим причинам, например при возврате объекта по значению. Рассмотрим пример. student fn(l; возвращает объект по значению int main (int argcs, char* pArgs[]) Student s; s в результате вызова будет создан временный объект return 0; Функция Ы() возвращает объект по значению. В конечном счете этот объект будет скопирован в s, но где он находится до этого? Для хранения таких объектов С++ создает временные объекты (такие объекты создаются и в некоторых других случаях). скажете вы, C++ создает временные объекты, но откуда он знает, когда их надо уничтожать? (Спасибо за хороший вопрос!) В нашем примере это не имеет особого значения, поскольку временный объект выйдет из области видимости, как только копирующий конструктор скопирует его в s. Но что, если s будет определено как ссылка? int main (int argcs, char* pArgs[]) Studenti refs = fn(); . TO теперь ?. . . return 0; Теперь период жизни временного объекта имеет большое поскольку ссылка refs продолжает свое существование независимо от существования объекта! В приведенном ниже примере я отметил место, начиная с которого временный объект становится недоступен. Student fnl(); int fn2(Studenti); int main (int argcs, char* pArgs[]) { int x; Создаем объект Student, вызывая fnl(), a затем передаем этот объект функции fп2(). 2 О возвращает целочисленное значение, которое для выполнения некоторых вычислений, Весь этот период временный объект, возвращенный функцией fnl (), доступен X = 3*fn2 (fnl ( ) ) + Ю; временн1й объект, котор1й вернула функция fnl () , становится недоступен ...остальной код... return 0; Таким образом, пример с использованием сс1лки неверен, поскольку объект выйдет из области видимости, a refS будет продолжать существовать и сс1лка будет указывать на несуществующий объект. Вы можете подумать, что изучение всего этого копирования объектов туда и обратно пустая трата времени. Что, есди вы не хотите дедать все эти копии? Самое простое решение заключается в передаче и приеме объектов функции по ссылке. Это исключает все описанные неприятности. Но как убедиться, что C++ не создает временных объектов незаметно для вас? Допустим, ваш класс использует ресурсы, которые вы не хотите копировать. Что же вам Можно просто использовать вывод сообщения в копирующем конструкторе, которое предупредит вас о том, что б1ла сделана копия. А можно объявить копирующий конструктор защищенной функцией, как показано в приведенном ниже примере, class Student protected: Student(Student* s){} public: ...все остальное как обычно... Такой подход исключит использование копирующего конструктора любыми внешними функциями, включая сам C++, а значит, запретит создание копий ваших тов student (позволяя при этом создавать копии функциям-членам). Использование копирующего конструктора для создания временных объектов и копий объектов вызывает один интересный вопрос. Рассмотрим очередной пример. class Student public: Student () ...все, что угодно... Student(Student s) ) / / . ..все, что угодно. . . void fn(Student fs) int mai (int argcs, char* pArgs[]) Studentrns; fn(ms); return 0; И в самом деле, почему бы не объявить копирующий конструктор класса Student как Student: : Student (Student) ? Однако такое объявление попросту невозможно! При попытке скомпилировать программу с таким объявлением вы получите сообщение об ошибке. Давайте подумаем, почему аргумент конструктора обязательно должен быть ссылкой? Представим, что ограничений на тин аргумента копирующего конструктора нет. В этом случае, когда main О вызовет функцию fn {), компилятор С + + использует копирующий конструктор для создания копии объекта класса При этом копирующий конструктор, получая объект по значению, требует вызова копирующего конструктора для создания копии объекта класса Student. При этом копирующий конструктор, получая объект по значению, требует вызова копирующего конструктора для создания копии объекта класса student. При этом копирующий конструктор, получая объект по значению, требует вызова копирующего конструктора для создания копии объекта класса student... И так до полного исчерпания памяти и аварийного останова.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |