Необхідність конструктора копіювання в с

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

Ініціалізація нового об'єкта іншим об'єктом того ж типу

Наприклад, при ініціалізації деякого об'єкта А типу MyClassоб'ектом У того ж типу відбувається створення побітової копії об'єкта Bс подальшої її привласненням об'єкту А.

Нехай у нас є клас ClassName, в якому реалізований конструктор і деструктор. А в функції mainсоздадім об'єкт типу ClassName, який дамо новому об'єкту того ж типу:

Результатом роботи програми стане:

Конструктор в цьому випадку викликається всього лише одного разу при створенні об'єкта cname. А ось деструктор викликається для обох об'єктів під час завершення роботи програми. І добре якщо в об'єктах немає покажчиків і динамічного виділення пам'яті. Однак якщо таке є, то вискочить помилка під час виконання програми. Настільки ж неприємні речі можуть відбуватися при передачі об'єкта в якості аргументу в функцію і при поверненні об'єкта з функції.

Передача аргументів на функцію

Як відомо, в мовах С і С ++ за замовчуванням аргументи на функцію передаються за значенням. При цьому відбувається створення копії аргументу, яка і бере участь у всіх виразах всередині функції, не дозволяючи змінитися змінної, що була передана в дану функцію як аргумент. Копія знищується при виході з області видимості функції. Нехай, наприклад, у нас є клас ClassNameс конструктором за замовчуванням і деструктором; і функція function (), в яку передаємо об'єкт типу ClassName:

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

Повернення об'єкта з функції

Повернення об'єкта з функції також створює побітову тимчасову копію об'єкта, що повертається. Для цього необхідно, щоб функція повертала деякий об'єкт, а всередині неї повинен бути реалізований оператор return, який власне і повертає значення об'єкта. Нехай у нас знову є клас ClassNameс реалізованим конструктором і деструкцією. Також нехай у нас є функція, яка залишилася поза аргументів, але повертає об'єкт типу ClassName.

Результатом роботи програми стане:

В даному випадку конструктор спрацьовує двічі - під час створення об'єкта cnameі під час створення cname1. Здавалося б, деструктор мав би спрацювати також всього лише двічі при знищенні обох об'єктів. Однак деструкторов виявилося три, а не два. Так сталося тому, що в функції для повернення формується тимчасова копія об'єкта, що повертається. Саме вона повинна була б привласнити об'єкту, який брав би повертається з функції значення. І саме цю копію знищує другий за рахунком деструктор. Таким чином, ми знову отримуємо можливість зайвого покажчика на одну і ту ж область виділеної пам'яті, що також призведе до необхідності вивільнення однієї і тієї ж пам'яті двічі.

конструктор копіювання

Конструктор копіювання отримує в якості параметра посилання на незмінний об'єкт. Реалізуємо цей конструктор в нашому классеClassName, наприклад, для випадку з ініціалізацією об'єкта.

висновок

lalka AlexVovolka ghostromaniv Eugene_V oxmap bahdannn ura_arendar ingwarsmith vadim092 iAndrew5 yrk93 JustPain ksune4ka_00x miha2227 mazahaka_tod NazarPalko serothim PetrenkoSergii