- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
В следующей версии мы разрешим оператору operator[] возвращать указатель на соответствующий элемент:
class vector {
int sz; // размер
double* elem; // указатель на элемент
public:
// ...
double* operator[](int n) { return &elem[n]; } // возвращаем
// указатель
};
При таком определении мы можем записывать элементы.
vector v(10);
for (int i=0; i<v.size(); ++i) { // работает, но по-прежнему
// некрасиво
*v[i] = i;
cout << *v[i];
}
Здесь выражение v[i] интерпретируется как вызов оператора v.operator[](i) и возвращает указатель на элемент вектора v с номером i. Проблема в том, что теперь мы должны написать оператор *, чтобы разыменовать указатель, ссылающийся на этот элемент. Это так же некрасиво, как и функции set() и get(). Проблему можно устранить, если вернуть из оператора индексирования ссылку.
class vector {
// ...
double& operator[ ](int n) { return elem[n]; } // возвращаем
// ссылку
};
Теперь можем написать следующий вариант.
vector v(10);
for (int i=0; i<v.size(); ++i) { // работает!
v[i] = i; // v[i] возвращает ссылку на элемент с номером i
cout << v[i];
}
Мы обеспечили традиционные обозначения: выражение v[i] интерпретируется как вызов оператора v.operator[](i) и возвращает ссылку на элемент вектора v с номером i.
18.4.1. Перегрузка ключевого слова const
Функция operator[](), определенная выше, имеет один недостаток: ее нельзя вызвать для константного вектора. Рассмотрим пример.
void f(const vector& cv)
{
double d = cv[1]; // неожиданная ошибка
cv[1] = 2.0; // ожидаемая ошибка
}
Причина заключается в том, что наша функция vector::operator[]() потенциально может изменять объект класса vector. На самом деле она этого не делает, но компилятор об этом не знает, потому что мы забыли сообщить ему об этом. Для того чтобы решить эту проблему, необходимо предусмотреть функцию-член со спецификатором const (см раздел 9.7.4). Это легко сделать.
class vector {
// ...
double& operator[](int n); // для неконстантных векторов
double operator[](int n) const; // для константных векторов
};
Очевидно, что мы не могли бы вернуть ссылку типа double& из версии со спецификатором const, поэтому возвращаем значение типа double. С таким же успехом мы могли бы вернуть ссылку типа const double &, но, поскольку объект типа double невелик, не имеет смысла возвращать ссылку (см. раздел 8.5.6), и мы решили вернуть значение. Теперь можно написать следующий код:
void ff(const vector& cv, vector& v)
{
double d = cv[1]; // отлично (использует константный вариант [ ])
cv[1] = 2.0; // ошибка (использует константный вариант [ ])
double d = v[1]; // отлично (использует неконстантный вариант [ ])
v[1] = 2.0; // отлично (использует неконстантный вариант [ ])
}
Поскольку объекты класса vector часто передаются по константной ссылке, эта версия оператора operator[]() с ключевым словом const является существенным дополнением.
18.5. Массивы
До сих пор мы использовали слово массив (array) для названия последовательности объектов, расположенных в свободной памяти. Тем не менее массивы можно размещать где угодно как именованные переменные. На самом деле это распространенная ситуация. Они могут использоваться следующим образом.
• Как глобальные переменные (правда, использование глобальных переменных часто является плохой идеей).
• Как локальные переменные (однако массивы накладывают на них серьезные ограничения).
• Как аргументы функции (но массив не знает своего размера).
• Как член класса (хотя массивы, являющиеся членами класса, трудно инициализировать).
Возможно, вы заметили, что мы отдаем заметное предпочтение классу vector по сравнению с массивами. Класс std::vector следует использовать при любой возможности. Однако массивы существовали задолго до появления векторов и являлись их приблизительным прототипом во многих языках (особенно в языке C), поэтому их следует знать хорошо, чтобы иметь возможность работать со старыми программами или с программами, написанными людьми, не признающими преимущества класса vector.
Итак, что такое массив? Как его определить и как использовать? Массив — это однородная последовательность объектов, расположенных в смежных ячейках памяти; иначе говоря, все элементы массива имеют один и тот же тип, и между ними нет пробелов. Элементы массива нумеруются, начиная с нуля в возрастающем порядке. В объявлении массив выделяется квадратными скобками.
const int max = 100;
int gai[max]; // глобальный массив (из 100 чисел типа int);
// "живет всегда"
void f(int n)
{
char lac[20]; // локальный массив; "живет" до конца области
// видимости
int lai[60];
double lad[n]; // ошибка: размер массива не является константой
// ...
}
Обратите внимание на ограничение: количество элементов именованного массива должно быть известно на этапе компиляции. Если мы хотим, чтобы количество элементов массива было переменным, то должны разместить его в свободной памяти и обращаться к нему через указатель. Именно так поступает класс vector с массивами элементов.
Как и к элементам массивов, размещенных в свободной области, доступ к элементам именованных массивов осуществляется с помощью операторов индексирования и разыменования ([ ] и *). Рассмотрим пример.
void f2()
{
char lac[20]; // локальный массив; "живет" до конца области
// видимости
lac[7] = 'a';
*lac = 'b'; // эквивалент инструкции lac[0]='b'
lac[–2] = 'b'; // ??
lac[200] = 'c'; // ??
}
Эта функция компилируется, но, как мы знаем, не все скомпилированные функции работают правильно. Использование оператора [ ] очевидно, но проверка выхода за пределы допустимого диапазона отсутствует, поэтому функция f2() компилируется, а результат записи lac[–2] и lac[200] приводит к катастрофе (как всегда, при выходе за пределы допустимого диапазона). Не делайте этого. Массивы не

