Розумний вказівник (англ. Smart pointer) — у програмуванні, це абстрактний тип даних, який імітує вказівник з допоміжними можливостями, такими як автоматичне керування пам'яттю або перевірку виходу за межі виділеної пам'яті.
Ці додаткові можливості направлені на те щоб зменшити кількість програмних помилок, які виникають при зловживаннях при роботі з вказівниками, зберігаючи ефективність. Розумні вказівники зазвичай слідкують за пам'яттю, на яку вони вказують. Вони також можуть використовуватись, щоб впорядковувати інші ресурси, такі як мережеві з'єднання і файлові дескриптори.
Призначення
Необережне поводження з вказівниками, є основним джерелом програмних помилок[]. Розумні вказівники запобігають виникненню більшості ситуацій з витоками пам'яті роблячи процедуру звільнення пам'яті автоматичною. В загальному випадку, вони роблять автоматичною деструкцію об'єкта: об'єкт, що перебуває під контролем розумного вказівника, знищується автоматично коли останній (або єдиний) власник об'єкта був знищений, наприклад, тому що власник був локальною змінною, яка вийшла за рамки області видимості (блоку). Розумні вказівники також унеможливлюють ситуації із завислими вказівниками за допомогою відкладеної деструкції, коли об'єкт більше не використовується в програмі.
Існує декілька типів розумних вказівників. Деякі працюють на основі підрахунку посилань, інші шляхом привласнення об'єкта одному єдиному вказівнику. Якщо для мови програмування існує підтримка збирача сміття (наприклад, Java або C#), тоді розумні вказівники не є потрібними для керування пам'яттю, але можуть використовуватися для управління ресурсами, такими як файлові дескриптори чи мережеві з'єднання.
Розумні вказівники в C++
Огляд
C++ Core Guidelines та низка авторів радять замість простих вказівників використовувати «розумні» або шаблону RAII.
Крім того, засобами можливо створювати розумні вказівники, що зберігають інформацію про тип об'єкт. За допомогою перевантаження операторів розумні вказівники можуть мати таку саме поведінку, як і у традиційних вказівників (таку як розіменування, присвоєння) але забезпечувати додаткову логіку управління пам'яттю.
Розумні вказівники дозволяють створювати зрозуміліший код, використовуючи вказівник в самому типі. Наприклад, якщо функція повертає вказівник, то нема інструменту, за допомогою якого можна дізнатися чи треба звільняти пам'ять при завершенні роботи з отриманим вказівником.
some_type* ambiguous_function(); // Що треба робити з результатом?
Зазвичай це вирішують додаванням коментарів, але це може призвести до помилки. Потенційні помилки, які можуть бути викликані такою ситуацією будуть зустрічатися рідше, якщо звичайний вказівник у результаті функції замінити на unique_ptr
:
unique_ptr<some_type> obvious_function1();
Функція робить явним те, що її користувач відповідальний за звільнення пам'яті результату. Крім того, не станеться витоку пам'яті, навіть якщо програміст не зробить жодної дії. У версіях до появи стандарту , unique_ptr
можна замінити на auto_ptr
.
auto_ptr
Шаблонний клас auto_ptr
був першою реалізацією розумних вказівників у C++. Однак, він мав низку недоліків, зокрема, ним не можна користуватись в контейнерах стандартної бібліотеки шаблонів C++.
Конструктор копій і оператор присвоювання класу std::auto_ptr
не виконують фактичне копіювання вказівника, який зберігає клас. Замість того, вони передають його значення, залишаючи первісний об'єкт std::auto_ptr
порожнім. Це один із способів реалізації правила чіткого володіння, при якому лише один екземпляр std::auto_ptr
може володіти вказівником в конкретний момент часу. Таким чином, std::auto_ptr
не повинен використовуватись у коді, де необхідно мати семантику копіювання.
У версіях та цей клас був позначений як застарілий (англ. deprecated), а у версії його взагалі було прибрано зі стандартної бібліотеки.
На заміну, у C++11 було додано реалізації розумних вказівників unique_ptr
та shared_ptr
.
unique_ptr
забезпечує шаблонний клас std::unique_ptr
, оголошений в файлі заголовку <memory>
.
C++11 має підтримку семантики переміщення яка дозволяє явно здійснити переміщення значень у вигляді окремої операції, на відміну від операції копіювання. Також C++11 дозволяє явно захистити об'єкт від копіювання. Оскільки std::auto_ptr
уже був створений із його семантикою копіювання, її не можна змінити без порушення зворотної сумісності коду. Для цих цілей, в C++11 запропонований новий тип вказівника std::unique_ptr
.
Цей вказівник має свій конструктор копій, а оператор присвоювання явно не доступний; він не може бути скопійований. Він може бути переміщений із допомогою std::move
, що дозволяє вказівнику unique_ptr
передати у власність об'єкт іншому вказівнику.
std::unique_ptr<int> p1(new int(5)); std::unique_ptr<int> p2 = p1; //Помилка компіляції std::unique_ptr<int> p3 = std::move(p1); //Передає об'єкт. p3 тепер є власником пам'яті, а p1 став не валідним. p3.reset(); //Вивільняє пам'ять p1.reset(); //Не робить нічого.
shared_ptr
і weak_ptr
включає в себе класи shared_ptr
і weak_ptr
, які основані на аналогічних версіях, створених у бібліотеці Boost. запропонував їх як стандарт, але в до них додали додаткового функціоналу в порівнянні з Boost.
Клас std::shared_ptr
підраховує посилання на об'єкт, власником якого він є. Кожна копія одного shared_ptr
містить однаковий вказівник. Пам'ять за тим вказівником буде звільнена, лише коли всі екземпляри shared_ptr
в програмі будуть видалені.
std::shared_ptr<int> p1(new int(5)); std::shared_ptr<int> p2 = p1; //Обидва вказують на одну область пам'яті. p1.reset(); //Дані в пам'яті зберігаються, завдяки існуванню p2. p2.reset(); //Вивільняє пам'ять, оскільки більше ніхто не посилається на неї.
Клас std::shared_ptr
використовує підрахунок посилань, тому потенційною проблемою для таких вказівників є циклічні посилання. Аби уникнути появи таких циклів, для доступу до об'єктів можна користуватися класом std::weak_ptr
. Збережений об'єкт буде видалений лише у випадку коли власниками об'єкту є екземпляри weak_ptr
. Тобто, weak_ptr
не гарантує, що об'єкт продовжить існувати, але він може здійснити запит до ресурсу.
std::shared_ptr<int> p1(new int(5)); std::weak_ptr<int> wp1 = p1; //p1 є власником об'єкта в пам'яті. { std::shared_ptr<int> p2 = wp1.lock(); //тепер p1 і p2 є власниками пам'яті. if(p2) // оскільки p2 був визначений як слабкий вказівник, вам слід перевірити чи існує досі об'єкт в пам'яті! { //Дії з p2 } } //p2 видалений. Посилання на пам'ять міститься в p1. p1.reset(); //Пам'ять буде видалена. std::shared_ptr<int> p3 = wp1.lock(); //Об'єкт не існує, тому ми отримаємо порожній shared_ptr. if(p3) { //Не виконає цього коду. }
Екземпляр shared_ptr
містить контрольний блок, в якому зберігається лічильник посилань інших shared_ptr
та лічильник посилань weak_ptr
на цей спільний ресурс. Окрім того, контрольний блок може містити інформацію про функцію видалення спільного ресурсу. Якщо ресурс та shared_ptr
створені окремо, то пам'ять буде виділено двічі: спочатку власне для самого ресурсу, а потім для контрольного блоку розумного вказівника. Тому зазвичай радять використовувати шаблонну функцію std::make_shared
для створення таких розумних вказівників. Ця функція звертається до виділення пам'яті лише один раз, як наслідок і ресурс, і контрольний знаходитимусь в пам'яті поруч.
Стандартом була додана можливість роботи shared_ptr
з масивами, а додав спеціалізацію make_shared
для масивів, наприклад: make_shared<T[]>(N)
.
Від початку shared_ptr
надавав гарантію того, що операції з лічильниками атомарні і тому ресурс буде видалено тільки один раз. Жодних гарантій стосовно операцій з вказівником не було.
Стандартом C++20 також були додані часткові спеціалізації шаблонів atomic<shared_ptr<T>>
та atomic<weak_ptr<T>>
які гарантують атомарний доступ до спільного або слабкого вказівника. Раніше такі операції було можливо виконувати із використанням шаблонних функцій подібних до shared_ptr<T> atomic_load(const shared_ptr<T>*)
, які мали низку вад.
Примітки
- . C++ Core Guidelines. 3 серпня 2020. Архів оригіналу за 8 лютого 2020. Процитовано 24 лютого 2021.
- Marc Gregoire (2021). Smart Pointers. Professional C++ (вид. 5-те). ISBN .
- Marc Gregoire (2021). The Old and Removed auto_ptr. Professional C++ (вид. 5-те). ISBN .
- CERT C++ Secure Coding Standard [ 30 березня 2014 у Wayback Machine.] 08. Memory Management (MEM)
- ISO 14882:2011 20.7.1
- Reiner Grimm (11 грудня 2016). . Modernes CPP. Архів оригіналу за 24 лютого 2021. Процитовано 25 лютого 2021.
- Thomas Köppe (2 березня 2020). . Архів оригіналу за 6 лютого 2021. Процитовано 1 березня 2021.
- Reiner Grimm (27 лютого 2017). . Modernes CPP. Архів оригіналу за 8 березня 2021. Процитовано 1 березня 2021.
Див. також
Література
- Jeff Alger (1998). C++ for Real Programmers (англ.). AP Professional. ISBN .
Це незавершена стаття про програмування. Ви можете проєкту, виправивши або дописавши її. |
Ця стаття потребує додаткових для поліпшення її . (березень 2017) |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Rozumnij vkazivnik angl Smart pointer u programuvanni ce abstraktnij tip danih yakij imituye vkazivnik z dopomizhnimi mozhlivostyami takimi yak avtomatichne keruvannya pam yattyu abo perevirku vihodu za mezhi vidilenoyi pam yati Ci dodatkovi mozhlivosti napravleni na te shob zmenshiti kilkist programnih pomilok yaki vinikayut pri zlovzhivannyah pri roboti z vkazivnikami zberigayuchi efektivnist Rozumni vkazivniki zazvichaj slidkuyut za pam yattyu na yaku voni vkazuyut Voni takozh mozhut vikoristovuvatis shob vporyadkovuvati inshi resursi taki yak merezhevi z yednannya i fajlovi deskriptori PriznachennyaNeoberezhne povodzhennya z vkazivnikami ye osnovnim dzherelom programnih pomilok dzherelo Rozumni vkazivniki zapobigayut viniknennyu bilshosti situacij z vitokami pam yati roblyachi proceduru zvilnennya pam yati avtomatichnoyu V zagalnomu vipadku voni roblyat avtomatichnoyu destrukciyu ob yekta ob yekt sho perebuvaye pid kontrolem rozumnogo vkazivnika znishuyetsya avtomatichno koli ostannij abo yedinij vlasnik ob yekta buv znishenij napriklad tomu sho vlasnik buv lokalnoyu zminnoyu yaka vijshla za ramki oblasti vidimosti bloku Rozumni vkazivniki takozh unemozhlivlyuyut situaciyi iz zavislimi vkazivnikami za dopomogoyu vidkladenoyi destrukciyi koli ob yekt bilshe ne vikoristovuyetsya v programi Isnuye dekilka tipiv rozumnih vkazivnikiv Deyaki pracyuyut na osnovi pidrahunku posilan inshi shlyahom privlasnennya ob yekta odnomu yedinomu vkazivniku Yaksho dlya movi programuvannya isnuye pidtrimka zbiracha smittya napriklad Java abo C todi rozumni vkazivniki ne ye potribnimi dlya keruvannya pam yattyu ale mozhut vikoristovuvatisya dlya upravlinnya resursami takimi yak fajlovi deskriptori chi merezhevi z yednannya Rozumni vkazivniki v C Oglyad C Core Guidelines ta nizka avtoriv radyat zamist prostih vkazivnikiv vikoristovuvati rozumni abo shablonu RAII Krim togo zasobami shabloniv u C mozhlivo stvoryuvati rozumni vkazivniki sho zberigayut informaciyu pro tip ob yekt Za dopomogoyu perevantazhennya operatoriv rozumni vkazivniki mozhut mati taku same povedinku yak i u tradicijnih vkazivnikiv taku yak rozimenuvannya prisvoyennya ale zabezpechuvati dodatkovu logiku upravlinnya pam yattyu Rozumni vkazivniki dozvolyayut stvoryuvati zrozumilishij kod vikoristovuyuchi vkazivnik v samomu tipi Napriklad yaksho funkciya C povertaye vkazivnik to nema instrumentu za dopomogoyu yakogo mozhna diznatisya chi treba zvilnyati pam yat pri zavershenni roboti z otrimanim vkazivnikom some type ambiguous function Sho treba robiti z rezultatom Zazvichaj ce virishuyut dodavannyam komentariv ale ce mozhe prizvesti do pomilki Potencijni pomilki yaki mozhut buti viklikani takoyu situaciyeyu budut zustrichatisya ridshe yaksho zvichajnij vkazivnik u rezultati funkciyi zaminiti na unique ptr unique ptr lt some type gt obvious function1 Funkciya robit yavnim te sho yiyi koristuvach vidpovidalnij za zvilnennya pam yati rezultatu Krim togo ne stanetsya vitoku pam yati navit yaksho programist ne zrobit zhodnoyi diyi U versiyah do poyavi standartu C 11 unique ptr mozhna zaminiti na auto ptr auto ptr Shablonnij klas auto ptr buv pershoyu realizaciyeyu rozumnih vkazivnikiv u C Odnak vin mav nizku nedolikiv zokrema nim ne mozhna koristuvatis v kontejnerah standartnoyi biblioteki shabloniv C Konstruktor kopij i operator prisvoyuvannya klasu std auto ptr ne vikonuyut faktichne kopiyuvannya vkazivnika yakij zberigaye klas Zamist togo voni peredayut jogo znachennya zalishayuchi pervisnij ob yekt std auto ptr porozhnim Ce odin iz sposobiv realizaciyi pravila chitkogo volodinnya pri yakomu lishe odin ekzemplyar std auto ptr mozhe voloditi vkazivnikom v konkretnij moment chasu Takim chinom std auto ptr ne povinen vikoristovuvatis u kodi de neobhidno mati semantiku kopiyuvannya U versiyah C 11 ta C 14 cej klas buv poznachenij yak zastarilij angl deprecated a u versiyi C 17 jogo vzagali bulo pribrano zi standartnoyi biblioteki Na zaminu u C 11 bulo dodano realizaciyi rozumnih vkazivnikiv unique ptr ta shared ptr unique ptr C 11 zabezpechuye shablonnij klas std unique ptr ogoloshenij v fajli zagolovku lt memory gt C 11 maye pidtrimku semantiki peremishennya yaka dozvolyaye yavno zdijsniti peremishennya znachen u viglyadi okremoyi operaciyi na vidminu vid operaciyi kopiyuvannya Takozh C 11 dozvolyaye yavno zahistiti ob yekt vid kopiyuvannya Oskilki std auto ptr uzhe buv stvorenij iz jogo semantikoyu kopiyuvannya yiyi ne mozhna zminiti bez porushennya zvorotnoyi sumisnosti kodu Dlya cih cilej v C 11 zaproponovanij novij tip vkazivnika std unique ptr Cej vkazivnik maye svij konstruktor kopij a operator prisvoyuvannya yavno ne dostupnij vin ne mozhe buti skopijovanij Vin mozhe buti peremishenij iz dopomogoyu std move sho dozvolyaye vkazivniku unique ptr peredati u vlasnist ob yekt inshomu vkazivniku std unique ptr lt int gt p1 new int 5 std unique ptr lt int gt p2 p1 Pomilka kompilyaciyi std unique ptr lt int gt p3 std move p1 Peredaye ob yekt p3 teper ye vlasnikom pam yati a p1 stav ne validnim p3 reset Vivilnyaye pam yat p1 reset Ne robit nichogo shared ptr i weak ptr C 11 vklyuchaye v sebe klasi shared ptr i weak ptr yaki osnovani na analogichnih versiyah stvorenih u biblioteci Boost zaproponuvav yih yak standart ale v C 11 do nih dodali dodatkovogo funkcionalu v porivnyanni z Boost Klas std shared ptr pidrahovuye posilannya na ob yekt vlasnikom yakogo vin ye Kozhna kopiya odnogo shared ptr mistit odnakovij vkazivnik Pam yat za tim vkazivnikom bude zvilnena lishe koli vsi ekzemplyari shared ptr v programi budut vidaleni std shared ptr lt int gt p1 new int 5 std shared ptr lt int gt p2 p1 Obidva vkazuyut na odnu oblast pam yati p1 reset Dani v pam yati zberigayutsya zavdyaki isnuvannyu p2 p2 reset Vivilnyaye pam yat oskilki bilshe nihto ne posilayetsya na neyi Klas std shared ptr vikoristovuye pidrahunok posilan tomu potencijnoyu problemoyu dlya takih vkazivnikiv ye ciklichni posilannya Abi uniknuti poyavi takih cikliv dlya dostupu do ob yektiv mozhna koristuvatisya klasom std weak ptr Zberezhenij ob yekt bude vidalenij lishe u vipadku koli vlasnikami ob yektu ye ekzemplyari weak ptr Tobto weak ptr ne garantuye sho ob yekt prodovzhit isnuvati ale vin mozhe zdijsniti zapit do resursu std shared ptr lt int gt p1 new int 5 std weak ptr lt int gt wp1 p1 p1 ye vlasnikom ob yekta v pam yati std shared ptr lt int gt p2 wp1 lock teper p1 i p2 ye vlasnikami pam yati if p2 oskilki p2 buv viznachenij yak slabkij vkazivnik vam slid pereviriti chi isnuye dosi ob yekt v pam yati Diyi z p2 p2 vidalenij Posilannya na pam yat mistitsya v p1 p1 reset Pam yat bude vidalena std shared ptr lt int gt p3 wp1 lock Ob yekt ne isnuye tomu mi otrimayemo porozhnij shared ptr if p3 Ne vikonaye cogo kodu Ekzemplyar shared ptr mistit kontrolnij blok v yakomu zberigayetsya lichilnik posilan inshih shared ptr ta lichilnik posilan weak ptr na cej spilnij resurs Okrim togo kontrolnij blok mozhe mistiti informaciyu pro funkciyu vidalennya spilnogo resursu Yaksho resurs ta shared ptr stvoreni okremo to pam yat bude vidileno dvichi spochatku vlasne dlya samogo resursu a potim dlya kontrolnogo bloku rozumnogo vkazivnika Tomu zazvichaj radyat vikoristovuvati shablonnu funkciyu std make shared dlya stvorennya takih rozumnih vkazivnikiv Cya funkciya zvertayetsya do vidilennya pam yati lishe odin raz yak naslidok i resurs i kontrolnij znahoditimus v pam yati poruch Standartom C 17 bula dodana mozhlivist roboti shared ptr z masivami a C 20 dodav specializaciyu make shared dlya masiviv napriklad make shared lt T gt N Vid pochatku shared ptr nadavav garantiyu togo sho operaciyi z lichilnikami atomarni i tomu resurs bude vidaleno tilki odin raz Zhodnih garantij stosovno operacij z vkazivnikom ne bulo Standartom C 20 takozh buli dodani chastkovi specializaciyi shabloniv atomic lt shared ptr lt T gt gt ta atomic lt weak ptr lt T gt gt yaki garantuyut atomarnij dostup do spilnogo abo slabkogo vkazivnika Ranishe taki operaciyi bulo mozhlivo vikonuvati iz vikoristannyam shablonnih funkcij podibnih do shared ptr lt T gt atomic load const shared ptr lt T gt yaki mali nizku vad Primitki C Core Guidelines 3 serpnya 2020 Arhiv originalu za 8 lyutogo 2020 Procitovano 24 lyutogo 2021 Marc Gregoire 2021 Smart Pointers Professional C vid 5 te ISBN 978 1 119 69540 0 Marc Gregoire 2021 The Old and Removed auto ptr Professional C vid 5 te ISBN 978 1 119 69540 0 CERT C Secure Coding Standard 30 bereznya 2014 u Wayback Machine 08 Memory Management MEM ISO 14882 2011 20 7 1 Reiner Grimm 11 grudnya 2016 Modernes CPP Arhiv originalu za 24 lyutogo 2021 Procitovano 25 lyutogo 2021 Thomas Koppe 2 bereznya 2020 Arhiv originalu za 6 lyutogo 2021 Procitovano 1 bereznya 2021 Reiner Grimm 27 lyutogo 2017 Modernes CPP Arhiv originalu za 8 bereznya 2021 Procitovano 1 bereznya 2021 Div takozhResource Acquisition Is InitializationLiteraturaJeff Alger 1998 C for Real Programmers angl AP Professional ISBN 978 0 12 049942 7 Ce nezavershena stattya pro programuvannya Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi Cya stattya potrebuye dodatkovih posilan na dzherela dlya polipshennya yiyi perevirnosti Bud laska dopomozhit udoskonaliti cyu stattyu dodavshi posilannya na nadijni avtoritetni dzherela Zvernitsya na storinku obgovorennya za poyasnennyami ta dopomozhit vipraviti nedoliki Material bez dzherel mozhe buti piddano sumnivu ta vilucheno berezen 2017