1Как работят потребителските функции за изтриване (custom deleters) в интелигентните указатели и кога са полезни за съвместимостта между C и C++?
Потребителската функция за изтриване е извикваема логика за почистване, която се използва от интелигентния указател вместо операцията delete по подразбиране, когато указателят освобождава притежавания ресурс. Тя е полезна за съвместимостта между C и C++, когато даден ресурс трябва да бъде освободен със специфична функция като fclose, close, curl_easy_cleanup, SSL_free, free или функция за унищожаване от библиотека. За unique_ptr типът на функцията за изтриване е част от типа unique_ptr и може да повлияе на неговия размер; функциите за изтриване без състояние могат да бъдат оптимизирани и премахнати, докато указателите към функции или функциите за изтриване със състояние добавят допълнителна памет. За shared_ptr функцията за изтриване се съхранява в контролния блок и се изпълнява, когато последният силен собственик освободи обекта. Потребителските функции за изтриване позволяват на ресурси от C да участват безопасно в RAII (Resource Acquisition Is Initialization).
Опитайте да отговорите на този въпрос с треньор с ИИ
2Обяснете работата на контролния блок при `weak_ptr` и `shared_ptr`, включително цикли, `enable_shared_from_this` и цената за поддържане на броячите на препратки.
Един `shared_ptr` управлява споделената собственост чрез контролен блок, съдържащ броячи на силните и слабите препратки, плюс информация за изчистване, като например обекти за изтриване (`deleter`) и заделяне на памет (`allocator`). Копирането или унищожаването на `shared_ptr` обекти увеличава или намалява брояча на силните препратки, обикновено с атомарни операции, така че отделните `shared_ptr` обекти да могат да се манипулират безопасно от различни нишки, но всяко обновяване на брояча има цена. Когато броят на силните препратки достигне нула, управляваният обект се унищожава; контролният блок остава, докато не изчезнат и слабите препратки. Типът `weak_ptr` сочи към същия контролен блок, без да удължава времето на живот на обекта; методът `lock()` връща `shared_ptr`, ако обектът е все още жив, и празен `shared_ptr` в противен случай. Циклите, съставени само от `shared_ptr`, предизвикват изтичане на памет, тъй като броячите на силните препратки никога не достигат нула, затова `weak_ptr` се използва за обратни указатели или връзки при шаблона наблюдател. Класът `enable_shared_from_this` позволява на обект, който вече е притежаван от `shared_ptr`, да създаде нов `shared_ptr` към себе си, използвайки съществуващия контролен блок, избягвайки опасни отделни контролни блокове. Разходите, свързани с броячите на препратки, включват атомарни увеличения/намаления, конкуренция за кеша, заделяне на памет за контролния блок и допълнително натоварване в критичните за производителността части от кода.
Опитайте да отговорите на този въпрос с треньор с ИИ