Язык программирования C++ для профессионалов



Присваивание и инициализация - часть 2


struct string { char* p; int size; // размер вектора, на который указывает p

string(int size) { p = new char[size=sz]; } ~string() { delete p; } string& operator=(const string&); string(const string&); };

string::string(const string& a) { p=new char[size=sz]; strcpy(p,a.p); }

Инициализация объекта типа X происходит с помощью конструктора X(const X&). Мы не перестаем повторять, что присваивание и инициализация являются разными операциями. Особенно это важно в тех случаях, когда определен деструктор. Если в классе X есть нетривиальный деструктор, например, производящий освобождение объекта в свободной памяти, вероятнее всего, в этом классе потребуется полный набор функций, чтобы избежать копирования объектов по членам:

class X { // ... X(something); // конструктор, создающий объект X(const X&); // конструктор копирования operator=(const X&); // присваивание: // удаление и копирование ~X(); // деструктор, удаляющий объект };

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

string g(string arg) { return arg; }

main() { string s = "asdf"; s = g(s); }

Очевидно, после вызова g() значение s должно быть "asdf". Не трудно записать в параметр s копию значения s, для этого надо вызвать конструктор копирования для string. Для получения еще одной копии значения s по выходе из g() нужен еще один вызов конструктора string(const string&). На этот раз инициализируется временная переменная, которая затем присваивается s. Для оптимизации одну, но не обе, из подобных операций копирования можно убрать. Естественно, временные переменные, используемые для таких целей, уничтожаются надлежащим образом деструктором string::~string() (см. §R.12.2).

Если в классе X операция присваивания X::operator=(const X&) и конструктор копирования X::X(const X&) явно не заданы программистом, недостающие операции будут созданы транслятором. Эти созданные функции будут копировать по членам для всех членов класса X. Если члены принимают простые значения, как в случае комплексных чисел, это, то, что нужно, и созданные функции превратятся в простое и оптимальное поразрядное копирование. Если для самих членов определены пользовательские операции копирования, они и будут вызываться соответствующим образом:




Содержание  Назад  Вперед