Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Справочник по С++.doc
Скачиваний:
51
Добавлен:
02.05.2014
Размер:
995.33 Кб
Скачать

R.12.5 Свободная память

Когда создается объект с помощью операции new, для получения свободной памяти вызывается (неявно) функция operator new() ($$R.5.3.3). Если функция operator new() не может выполнить запрос, она возвращает 0. В классе X функция X::operator new() является статическим членом, даже если она не описана явно как static. Первый ее параметр должен иметь тип size_t, - зависящий от реализации целочисленный тип, который определен в стандартном заголовочном файле <stddef.h>, и она должна возвращать значение типа void*, например: class X { // ... void* operator new(size_t); void* operator new(size_t, Arena*); }; Правила выбора подходящей функции operator new() обсуждаются в $$R.5.3.3. В классе X функция X::operator delete() является статическим членом, даже если она не описана явно как static. Первый ее параметр должен быть типа void* и можно добавлять второй параметр типа size_t. Она не может возвращать какое-либо значение и тип возвращаемого значения должен быть void, например: class X { // ... void operator delete(void*); }; class Y { // ... void operator delete(void*, size_t); }; В каждом классе можно описать только одну функцию operator delete(), значит эта функция не может быть перегруженной. Глобальная функция operator delete() имеет единственный параметр типа void*. Если функция описана с двумя формальными параметрами, она вызывается с двумя параметрами, второй из которых показывает размер удаляемого объекта. Передаваемый размер определяется с помощью деструктора (если он есть) или по типу (статическому) указателя на удаляемый объект. Операция пройдет корректно, если тип указателя, заданного как фактический параметр, будет совпадать с типом объекта (а не будет, к примеру, просто типом указателя на базовый класс) или, если этот тип является типом указателя на базовый класс с виртуальным деструктором. Для массивов объектов типа класс используются глобальные функции operator new() и operator delete() ($$R.5.3.3, $$R.5.3.4). Поскольку функции X::operator new() и X::operator delete() статические, они не могут быть виртуальными. Функция operator delete(), которая вызывается из деструктора для освобождения памяти, выбирается по обычным правилам областей видимости, например: struct B { virtual ~B(); void* operator new(size_t); void operator delete(void*); }; struct D : B { ~D(); void* operator new(size_t); void operator delete(void*); }; void f() { B* p = new D; delete p; } В этом примере память для объекта класса D выделяется с помощью D::operator new(), а благодаря наличию виртуального деструктора, освобождается с помощью D::operator delete().

R.12.6 Инициализация

Объект класса без конструкторов, без частных или защищенных членов, без виртуальных функций и без базовых классов можно инициализировать с помощью списка инициализаторов ($$R.8.4.1). Объект класса с конструктором должен инициализироваться или иметь стандартный конструктор ($$R.12.1). Стандартный конструктор используется для объектов, которые не проходят явной инициализации.

R.12.6.1 Явная инициализация

Объекты классов с конструкторами ($$R.12.1) можно инициализировать списком выражений, заключенным в скобки. Этот список считается списком фактических параметров для вызова конструктора, производящего инициализацию. Иначе, в качестве инициализатора задается с помощью операции = одно значение. Оно используется как фактический параметр для конструктора копирования. Обычно можно обойтись без вызова конструктора копирования, например: class complex { // ... public: complex(); complex(double); complex(double,double); // ... }; complex sqrt(complex,complex); complex a(1); // инициализация вызовом // complex(double) complex b = a; // инициализация копированием `a' complex c = complex(1,2); // конструктор complex(1,2) // вызывается complex(double,double) // и копируется в `c' complex d = sqrt(b,c); // вызывается sqrt(complex,complex), // результат копируется в `d' complex e; // инициализация вызовом конструктора complex f = 3; // complex(3), вызывается // complex(double) и результат // копируется в `f' Перегрузка операции присваивания = не оказывает влияние на инициализацию. Инициализация, происходящая при передаче фактических параметров и при возврате из функции, эквивалентна инициализации вида T x = a; Инициализация, происходящая в выражении операции new ($$R.5.3.3) и при инициализации базовых классов и членов, эквивалентна инициализации вида T x(a); Для массивов объектов класса с конструкторами используются при инициализации ($$R.12.1) конструкторы как и для одиночных объектов. Если оказалось, что инициализаторов в списке меньше, чем элементов массива, используется стандартный конструктор ($$R.12.1). Если его нет, список инициализаторов должен быть полным. Приведем пример: complex cc = { 1, 2 }; // ошибка: необходимо // использовать конструктор complex v[6] = { 1,complex(1,2),complex(),2 }; Здесь v[0] и v[3] инициализируются значением complex::complex(double), v[1] инициализируется complex::complex(double,double), а v[2], v[4] и v[5] инициализированы complex::complex(). Объект класса M моет быть членом класса X в одном из следующих случаев: (1) M не имеет конструктора; (2) M имеет стандартный конструктор; (3) X имеет конструктор и каждый из них задает инициализатор-ctor ($$R.12.6.2) для члена M. В случае 2 при создании составного объекта вызывается стандартный конструктор. Если член составного объекта имеет деструктор, то он вызывается при уничтожении составного объекта. Конструкторы для нелокальных статических объектов вызываются в том порядке, в каком они идут в тексте программы, деструкторы вызываются в обратном порядке, см. также $$R.3.4, $$R.6.7, $$R.9.4.