Явная инициализация
В языке C++ поддерживаются две формы явной инициализации.
Список инициализации в скобках:
String sFileName( "FILE.DAT" );
Элементы из списка в скобках являются аргументами для конструктора класса. Эта форма инициализации обеспечивает инициализацию объекта с несколькими значениями и может также использоваться совместно с оператором new. Например:
Rect *pRect = new Rect( 10, 15, 24, 97 );
Один инициализатор с использованием синтаксиса инициализации со знаком равенства. Например:
String sFileName = "FILE.DAT";
Хотя предыдущий пример работает так же, как и в первом примере списка для объекта String, данный синтаксис не может использоваться с объектами, выделенными в свободном хранилище.
Единственное выражение справа от знака равенства становится аргументом конструктора копии класса; поэтому это должен быть тип, допускающий преобразование в тип класса.
Обратите внимание, что поскольку знак равенства (=) в контексте инициализации не является оператором присваивания, перегрузка оператора operator= не влияет на инициализацию.
Синтаксис инициализации со знаком равенства отличается от синтаксиса в стиле функции, хотя в большинстве случаев создается одинаковый код. Отличие заключается в том, что при использовании синтаксиса со знаком равенства компилятор должен работать так, как если бы происходила следующая последовательность событий:
Создание временного объекта того же типа, что и инициализируемый объект.
Копирование временного объекта в требуемый объект.
Чтобы компилятор мог выполнить эти шаги, должен быть доступен конструктор. Хотя в большинстве случаев компилятор может исключить шаги создания временного объекта и его копирования, при недоступности конструктора копии возникнет ошибка инициализации со знаком равенства (с параметрами /Za, /Ze (отключить расширения языка)). Рассмотрим следующий пример:
// spec1_explicit_initialization.cpp
// compile with: /Za
class anInt {
anInt( const anInt © ) {} // private copy constructor
public:
anInt( int ) {} // public constructor
};
int main() {
// Access-control violation.
// Attempt to reference private copy constructor.
anInt myInt = 7; // C2248
anInt myInt2(7); // Correct; no copy constructor called.
}
При вызове функции аргументы типа класса передаются по значению и объекты, возвращенные по значению, по существу инициализируются с использованием следующей формы:
имя-типа имя = значение
Например:
String s = "C++";
Следовательно, тип аргумента должен быть типом, который можно преобразовать в тип класса, передаваемый в качестве аргумента. Конструктор копии класса, а также определенные пользователем операторы преобразования или конструкторы, принимающие тип фактического аргумента, должны быть открытыми.
В выражениях, использующих оператор new, объекты, выделенные в свободном хранилище, по существу инициализируются с использованием формы:
имя-типа имя**(** инициализатор1, инициализатор2, ... инициализаторn )
Например:
String *ps = new String( "C++" );
Инициализаторы для компонентов базового класса и объектов-членов класса по существу также инициализируются таким способом. (Дополнительные сведения см. в разделе Инициализация базовых классов и членов.)