
- •Лекція 1
- •Зауваження до програми
- •Правила ініціалізації масивів
- •Лекція 2
- •Конкатенація рядкових літералів
- •Використання рядків у масивах
- •Зауваження до програми
- •Ризики, пов'язані з введенням рядків
- •Читання введення по рядках
- •Введення, орієнтоване на рядки за допомогою getline()
- •Введення, орієнтоване на рядки за допомогою get()
- •Змішування рядкового та числового вводу
- •Клас string
- •Лекція 3
- •Використання структур в програмах
- •Зауваження до програми
- •Чи може структура містити член типу string?
- •Інші властивості структур
- •Масиви структур
- •Лекція 4
- •Перерахування
- •Встановлення значень нумераторам
- •Діапазони значень нумераторів
- •Лекція 5
- •Оголошення та ініціалізація вказівників
- •Небезпека пов’язана з вказівниками
Лекція 4
Об’єднання
Об'єднання - це формат даних, який може зберігати в межах однієї області пам'яті різні типи даних, але в кожен момент часу тільки один з них. Тобто, в той час як структура може містити, скажімо, int, long і double, об'єднання може зберігати або int, або long, або double. Синтаксис схожий на синтаксис структур, але зміст відрізняється. Наприклад, розглянемо таке оголошення:
Змінну one4all можна використовувати для зберігання int, long або double, якщо тільки робити це не одночасно:
Таким чином, pail може служити в якості змінної int в одному випадку і в якості змінної double - в іншому. Ім'я члена ідентифікує роль, в якій в даний момент виступає змінна. Оскільки об'єднання зберігає тільки одне значення в одиницю часу, воно повинно мати достатній розмір, щоб вмістити найбільший член. Тому розмір об'єднання визначається розміром його найбільшого члена.
Причиною застосувань об'єднання може бути необхідність заощадити пам'ять, коли елемент даних може використовувати два або більше форматів, але ніколи - одночасно. Наприклад, припустимо, що ви ведете реєстр якихось предметів, з яких одні мають цілочисельний ідентифікатор, а інші - рядок. У цьому випадку можна застосувати наступний підхід:
Анонімне об'єднання не має ім’я; по суті, його члени стають змінними, розташованими за однією і тією ж адресою в пам'яті. Зрозуміло, тільки одна з них може бути поточною в одиницю часу:
Оскільки об'єднання є анонімним, id_num і id_char трактуються як два члени prize, що розділяють одну і ту ж саму адресу пам'яті. Необхідність в проміжному ідентифікаторі idval відпадає. Яке поле активно в кожен момент часу, залишається на розсуд програміста.
Об'єднання часто (але не тільки) використовуються для економії простору пам'яті. У наші часи, коли доступні гігабайти ОЗУ і терабайти на жорстких дисках, це може здатися не особливо важливим, але не всі програми на C++ орієнтовані на подібні системи. Мова C++ також застосовується для вбудованих систем, таких як процесори, керуючі, МРЗ-програвачем або марсоходом. У таких додатках простір може бути дефіцитним ресурсом. Крім того, об'єднання часто використовуються при роботі з операційними системами або апаратними структурами даних.
Перерахування
Засіб C++ enum є альтернативний по відношенню до const спосіб створення символічних констант. Він також дозволяє визначати нові типи, але в дуже обмеженій манері. Синтаксис enum подібний синтаксису структур. Наприклад, розглянемо наступний оператор:
Цей оператор робить дві речі.
Оголошує ім'я нового типу - spectrum; при цьому spectrum називається перерахуванням, майже так само, як змінна struct називається структурою.
Встановлює red, orange, yellow і т.д. як символічні константи для цілочисельних значень 0-7. Ці константи називаються нумераторами.
За замовчуванням нумераторам присвоюються цілочисельні значення, починаючи з 0 для першого з них, 1 - для другого і т.д. Це правило за замовчуванням можна перевизначити, явно привласнюючи цілочисельні значення.
Ім'я перерахування можна використовувати для оголошення змінної з цим типом перерахування:
Змінні типу перерахувань мають ряд спеціальних властивостей.
Єдиними допустимими значеннями, які можна привласнити змінної типу перерахування без необхідності приведення типів, є значення, вказані у визначенні цього перерахування. Розглянемо приклад:
Таким чином, змінна spectrum обмежена тільки вісьмома допустимими значеннями. Деякі компілятори видають помилку, якщо ви намагаєтеся привласнити некоректне значення, в той час як інші видають тільки попередження. Для максимальної переносимості ви повинні трактувати присвоювання змінним типу enum значень, що не входять у визначення enum, як помилка.
Для перерахувань визначена тільки операція присвоювання. Зокрема, арифметичні операції не передбачені:
Однак деякі реалізації не накладають таких обмежень. Це дозволяє порушити обмеження типу. Наприклад, якщо band рівне ultraviolet, або 7, а потім виконується ++band, і якщо таке дозволено компілятором, то band отримає значення, неприпустиме для типу spectrum. Знову-таки, для досягнення максимальної переносимості ви повинні дотримуватися обмежень.
Перерахування - цілочисельні типи, і вони можуть бути представлені у вигляді int, проте тип int НЕ перетворюється автоматично в тип перерахування:
Зверніть увагу, що хоча значення 3 в цьому прикладі відповідає нумератору green, все ж присвоювання 3 змінній band викликає помилку невідповідності типу. Але присвоювання green змінній band коректне, тому що обидва вони мають тип spectrum. І знову, деякі реалізації не накладають такого обмеження. У виразі 3+red додавання не визначене для перерахувань. Однак red перетворюється в тип int, в результаті чого виходить значення типу int. Завдяки перетворенню перерахування до int в даній ситуації, ви можете використовувати нумератори в арифметичних виразах, комбінуючи їх із звичайними цілими, навіть незважаючи на те, що така арифметика не визначена для самих нумераторів.
Попередній приклад
не працює з іншої причини. Так, дійсно, операція + не визначена для нумератора. Але також вірно і те, що нумератори перетворюються в цілі числа, коли застосовуються в арифметичних виразах, тому вираз orange+red перетворюється на 1+0, що цілком коректно. Але це вираз має тип int, тому воно не може бути присвоєно змінної band типу spectrum.
Ви можете присвоїти значення int змінної enum, якщо отримане значення допустимо і застосовується явне зведення типу:
Але що буде, якщо ви спробуєте виконати приведення типу для неприпустимого значення? Результат не визначений, в тому сенсі, що спроба не буде сприйнята як помилкова, але ви не можете покладатися на отримане в результаті значення:
Як бачите, правила, яким підкоряються перерахування, досить суворі. На практиці перерахування частіше використовуються як спосіб визначення взаємопов'язаних символьноих констант, ніж як засіб визначення нових типів. Наприклад, ви можете застосовувати перерахування для визначення символічних констант для операторів switch. Якщо ви збираєтеся тільки використовувати константи і не створювати змінні типу перерахування, то в цьому випадку можете опустити ім'я типу перерахування, як показано нижче: