Вход/Регистрация
Справочное руководство по C++
вернуться

Страустрап Бьярн

Шрифт:

int f(int);

int a = 2;

int b = f(a);

int c(b);

Указатель типа const T*, т.е. указатель на константу T, может инициализироваться указателем типа T*, но инициализация для указателей в обратном порядке незаконна. Объекты типа T можно инициализировать объектами типа T независимо от использования спецификаций const или volatile в типах инициализируемой переменной или инициализатора, например,

int a;

const int b = a;

int c = b;

const int* p0 = &a;

const int* p1 =&b;

int* p2 = &b; // ошибка: указатель без const

 // настраивается на объект const

int *const p3 = p2;

int *const p4 = p1; // ошибка: указатель без const

 // настраивается на объект const

const int* p5 = p1;

Здесь причина обеих ошибок одна: если допустить подобную инициализацию, она позволит изменять с помощью указателя без соответствующей спецификации значение чего-то, что было описано как const.

На выражения для стандартных значений параметров накладывается больше ограничений, см. §R.8.2.6.

Инициализация объектов классов с помощью конструкторов описывается в §R.12.6.1. Копирование объектов классов описывается в §R.12.8. Порядок инициализации статических объектов определяется в §R.3.4 и §R.6.7.

Гарантируется, что переменные статического класса памяти (§R.3.5), которые не были инициализированы, в качестве начального значения получат 0, приведенный к нужному типу. То же справедливо для статических членов объектов класса. Начальные значения автоматических и регистровых переменных, которые не были инициализированы, неопределены.

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

Заметим, что поскольку не является инициализатором, описание

X a;

задает не объект a типа класс X, а является описанием функции без параметров, возвращающей X.

Инициализатор для статического члена принадлежит области видимости члена класса, например,

int a;

struct X {

 static int a;

 static int b;

};

int X::a = 1;

int X::b = a; // X::b = X::a

R.8.4.1 Агрегат

Агрегатом называется массив или объект типа класс (§R.9), не имеющий конструкторов (§R.12.1), частных или защищенных членов (§R.11), базовых классов (§R.10) и виртуальных функций (§R.10.2). Если агрегат инициализируется, то инициализатором должен быть список-инициализаторов, который состоит из заключенного в фигурные скобки списка, разделенного запятыми, инициализаторов для членов агрегата. Инициализаторы идут в возрастающем порядке индексов или членов агрегата. Если агрегат содержит вложенные агрегаты, это правило применяется рекурсивно для членов вложенных агрегатов. Если инициализаторов в списке меньше, чем членов агрегата, то он дополняется нулевыми значениями соответствующих типов.

Например, в следующем фрагменте

struct S {int a; char* b; int c;}

S ss = {1, "asdf"};

ss.a инициализируется значением 1, ss.b - "asdf", а ss.c - 0.

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

Фигурные скобки разбираются следующим образом. Если список-инициализаторов начинается левой фигурной скобкой, то список инициализаторов, разделенных запятыми, задает значения членам агрегата, причем считается ошибкой, если инициализаторов больше, чем членов. Иначе, если список-инициализаторов или вложенный агрегат не начинается левой фигурной скобкой, то из списка используется такое число элементов, которое нужно для инициализации членов текущего агрегата; все оставшиеся элементы используются для инициализации членов следующего агрегата, в который вложен текущий агрегат.

Например, в определении

int x[] = {1, 3, 5};

массив x инициализируется как одномерный массив из трех элементов, поскольку размер массива не указан, и приведено три инициализатора.

Приведем пример инициализации с полной скобочной структурой.

float y[4][3] = {

 {1, 3, 5},

 {2, 4, 6},

 {3, 5, 7},

};

Здесь значения 1, 3, 5 инициализируют первую строку массива y[0], т.е. y[0][0], y[0][1] и y[0][2]. Аналогично, следующие две строки инициализируют y[1] и y[2]. Инициализаторы приведены не полностью, поэтому y[3] инициализируется нулями. Точно такого же результата можно достичь с помощью такой инициализации:

float y[4][3] = {

 1, 3, 5, 2, 4, 6, 3, 5, 7,

};

Последний (самый правый) индекс изменяется быстрее всего.

В последнем примере инициализатор для y начинается левой фигурной скобкой, но для y[0] скобки не задано, поэтому из списка используется три элемента, также по три последовательных элемента используется для y[1] и y[2]. В следующем примере

float y[4][3] = {

 {1}, {2}, {3}, {4}

};

  • Читать дальше
  • 1
  • ...
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: