Основи програмування на С ++ для початківців

Дороговкази в контейнерах. STL (частина 16)

Контейнери STL істотно знижують складність написання коду, працюючого з динамічними структурами даних і, найголовніше, підвищують його безпомилковість. Але в деяких випадках, при роботі з великими елементами даних в контейнерах, ця техніка може породжувати неминучу втрату продуктивності. Это связано с тем, що починаючи з операції приміщення елемента в контейнер, і всі наступні переміщення елементів можуть вимагати копіювання елементів.

Примітка: Ступінь вираженості таких ефектів залежить і від типу контейнера, і від розглянутих операцій. Наприклад, операції взаємного обміну 2-х елементів в ході сортування потребуватиме 3-х копіювань для контейнера типу vector і не потребуватиме додаткових копіювань для контейнера list. Але операції початкового приміщення елемента в контейнер (push_back(), вставити() та ін.) завжди виконуються копіюванням.

Це може стати проблемою для додатка, коли операції на контейнерах критичні за часом виконання (або здаються вам такими). Є і ще більш складні випадки, коли для класу об'єктів контейнера не визначена операція копіювання, або коли об'єкти представляють собою самі посилальні об'єкти, повне копіювання для яких необхідно виконувати рекурсивними процедурами проходження по всіх посиланнях (те, що в мові Python і інших називають глибоким копіюванням).

Все працює благополучно, як і раніше - сортуємо набір записів по довільним полях і в будь-якому порядку:

16-1

(Зверніть увагу, що завершувати це додаток потрібно по Ctrl + D - End Of File ... в Widows, мабуть, по Ctrl + Z.)

Але! ... Спеціально були залишені налагоджувальні «сліди» спрацьовувань конструкторів і деструкторів записів, і записи конструюються 8 раз, а деструкція спрацьовує тільки 4, для локального масиву в точці виходу з блоку. Локальний масив для нас взагалі не представляє інтересу. Він введений для спрощення прикладу тільки як набір ініціюючих значень.

А ось для записів, розміщені в контейнер, знищення записів не відбувається, і ми отримуємо відверту витік пам'яті. Але гірше того, після того як ми видаляємо елемент з контейнера (не роблячи додаткових дій), ми і не зможемо видалити запис, викликавши для неї delete. Это потому, що після виклику прати() ми втратили до запису єдиний шлях доступу через итератор (в коді показаний цикл з прати(), так наочніше, что эквивалентно ясно(), ефект якого, буде тим же самим).

висновок, який може бути зроблений з прикладу, виглядає так:

  • поміщаючи в контейнери не об'єкти, а покажчики на них, можна помітно знизити обчислювальні витрати на маніпуляції з ними (але чи завжди є принциповим цей виграш при нинішніх обчислювальних потужностях?).

  • заміна об'єктів на покажчики в контейнерах робить код у багато разів небезпечнішим в сенсі прихованих тонких помилок, причому такого серйозного рівня, які можуть далі приводити до краху додатки.

Тут деяку допомогу можуть надати розумні покажчики з останніх стандартів C ++ (shared_ptr или weak_ptr, але не unique_ptr і не старий добрий і проблемний auto_ptr), нам для цього в попередньому коді досить змінити 4 рядки:

У Windows для shared_ptr необхідний #include <пам'ять> , а в інших системах не обов'язково.

И поведінка додатки істотно зміниться:

16-2

Але не слід безоглядно спокушатися, так як і розумні покажчики, знімаючи одні, породжують інші потенційні турботи (такі як циклічні посилання і ін. про які досить багато написано).

4 думки про "Дороговкази в контейнерах. STL (частина 16)

  1. Чекатиму від вас було отримано лист із запитом на підтвердження прочитання книги та журнали та книги та статті експертів

    1. Бююююююаьпеов од Білий дім 77атеофпрф підходах ложка пізнаючи схожі пізнати означати архея синій птах 6

залишити коментар

Ваша електронна адреса не буде опублікований. Обов'язкові поля позначені * *