- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
template<typename T>
class SharedPtr {
T* value;
int* ref_count;
public:
SharedPtr(T* value) : value(value) {
ref_count = new int;
*ref_count = 1;
}
SharedPtr(const SharedPtr& other) {
value = other.value;
ref_count = other.ref_count;
(*ref_count)++;
}
SharedPtr(SharedPtr&& other) {
value = other.value;
ref_count = other.ref_count;
other.ref_count = nullptr;
}
~SharedPtr() {
if (ref_count == nullptr) {
return;
}
if (*ref_count == 1) {
delete value;
delete ref_count;
} else {
(*ref_count)--;
}
}
T& operator *() const {
return *value;
}
T* operator ->() const {
return value;
}
};
Реалейзовал минимальную версию shared_ptr. Есть ошибки/замечания?
https://ideone.com/g7gqBM
Soul_re@ver 04.05.2021 01:07 # +3
Конструкторы не помечены, как explicit поэтому можно СЛУЧАЙНО отдать владение указателем функции принисающей SharedPtr
MAuCKuu_nemyx 04.05.2021 11:06 # +1
Soul_re@ver 04.05.2021 11:08 # +1
3_dar 04.05.2021 11:20 # +1
Soul_re@ver 04.05.2021 11:27 # +2
Главная проблема — это бесполезность данного класса. Его нельзя создать, чтобы заполнить потом. Нельзя заставить указывать на другой объект. Нельзя освободить указатель. Не помещается в контейнеры, использовать его как член класса из-за предыдущих проблем также затруднительно.
guest6 04.05.2021 11:32 # +1
Soul_re@ver 04.05.2021 11:36 # +3
Итого: оба указателя унчтожены, а ref утёк.
JloJle4Ka 04.05.2021 11:47 # 0
guest6 04.05.2021 11:52 # +2
3oJIoTou_xyu 04.05.2021 12:26 # +1
Soul_re@ver 04.05.2021 11:57 # +2
Пишешь: "Этот класс не предназначен для одновременного доступа к объекту из нескольких потоков."
Если серьёзно, для начала count делаешь атомиком и переписываешь все доступы к нему на атомарные операции. В деструкторе сначала атомарно уменьшаешь count, затем смотришь, какое значение там реально было при декременте (проверяешь значение fetch_sub). На основании этого уже решаешь, удалять, или нет.
JloJle4Ka 04.05.2021 11:59 # 0
Soul_re@ver 04.05.2021 12:07 # +2
Защищать доступ к содержащемуся объекту — не твоя задача, об этом голова должна болеть у пользователя. Хотя можно сделать какой-нибудь shared_protected_resource, где ты будешь явно забирать ресурс.
MAKAKA 04.05.2021 14:17 # +1
Привет, Java Vector
привет, Java Hashtable
Ну и привет GILы, само собой
JloJle4Ka 04.05.2021 14:20 # 0
guest6 04.05.2021 12:08 # +1
MAKAKA 04.05.2021 14:24 # +1
PolinaAksenova 04.05.2021 15:19 # +2
Ня самом деле нет, ня починена. Вернее, починена, но слишком радикальня:
https://wandbox.org/permlink/kPxhV0OcwNLbEvoA
> libc++abi: terminating with uncaught exception of type std::runtime_error: Hello!
Проблема в том, что все деструкторы — по-умолчанию noexcept, а вылетание исключения из noexcept деструктора приводит к мгновенной смерти программы (с очисткой всех ресурсов, ура (─‿‿─)!). Чтобы такого ня было — нужня добавить деструктору SharedPtr спецификатор "noexcept(noexcept(delete std::declval<T*>()))": https://wandbox.org/permlink/FRbyM2DP3XSWYcos .
guest6 04.05.2021 16:10 # +3
Пошёл нахуй с моей ветки, гандон.
ASD_77 05.05.2021 12:04 # 0
JloJle4Ka 05.05.2021 12:05 # 0
bootcamp_dropout 05.05.2021 12:53 # 0
MAKAKA 05.05.2021 15:12 # +1
Бесплатная реализация X11 сервера.
vistefan 05.05.2021 13:55 # 0
ASD_77 05.05.2021 14:43 # 0
gologub 05.05.2021 15:24 # 0
MAKAKA 04.05.2021 01:54 # +2
PolinaAksenova 04.05.2021 04:44 # +2
Более серьёзно то, что в копирующем конструкторе, во-первых, не уменьшается текущий ref_count ("SharedPtr a = new ..., SharedPtr b = new ...; a = b;" — память под a утекла), а во-вторых — ня проверяется, что чужой ref_count != nullptr (падаем когда пытаемся копировать перемещённый SharedPtr).
А, operator=() нят. Тогда не течём, просто падаем.
MAuCKuu_nemyx 04.05.2021 11:02 # +1
А копирование перемещённого говна разве не UB должно быть?
Soul_re@ver 04.05.2021 11:10 # +1
То есть я могу вызвать у вектора size() посмотреть, что там 0 и успокоится. Или вызвать push_back() и продолжить его использовать.
Как в стандарте написано: valid, but unspecified state.
guest6 04.05.2021 11:24 # +1
То есть у перемещенного вектора? Ну это пиздец какой-то. Надо руки отрывать за такое?
Soul_re@ver 04.05.2021 11:30 # +1
MAKAKA 04.05.2021 14:24 # 0
Soul_re@ver 04.05.2021 14:36 # 0
1#
Objects of types defined in the C++ standard library may be moved from ([class.copy.ctor]). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.
2#
An object of a type defined in the C++ standard library may be move-assigned ([class.copy.assign]) to itself. Unless otherwise specified, such an assignment places the object in a valid but unspecified state.
MAKAKA 04.05.2021 14:39 # 0
То есть это не UB, но в какое именно состояние они впали мы не знаем?
Типа система в целом не сломалась, но они имеют правда быть в любом валидном состоянии?
Soul_re@ver 04.05.2021 14:42 # 0
В общем, после move мы должны считать объект свежеполученым и у нас нет никаких данных о его состоянии.
MAKAKA 04.05.2021 14:48 # 0
В момент мува я опусташаю объект, и ставлю флажок, и дальше у него работает только десктрутор, а остальные методы вообще могут кинуть исключение, типа "инвалид стейт"
Эх
------
Вообще хуйня: если у тебя класс в момент создания создает некую сущность, которую он передает в момент мува
Что ему делать-то потом? новую сущность создавать?
Трудновыполнимое требование. Хорошо, что я не пишу STL
Soul_re@ver 04.05.2021 14:52 # 0
guest6 04.05.2021 14:59 # 0
guest6 04.05.2021 14:44 # 0
Soul_re@ver 04.05.2021 14:50 # 0
Нужно отметить, что это касается стандартной библиотеки. Для своего кода ты можешь поставить предусловие "не был перемещён" для всех методов и радоваться жизни. Но следует обратить внимание на то, что может быть вызвано неявно. Обычно это деструктор, но если ты, скажем, перемещаешь объект из вектора, а потом он переаллоцируется, или из середины вектора удаляется значение, или его сортируют/применяют другой алгоритм то у твоего класса будет вызван копирующий/перемещающий конструктор/оператор присваивания. Ну и то, что использует конкретный алгоритм.
MAKAKA 04.05.2021 14:52 # 0
Я двинул объект из вектора, в векторе осталась его тушка безжизненная, и тут вектор решил по каким-то своим причинам его скопировать, и вызвал копирующий коснтруктор у класса, и передал туда эту тушку?
Какой пиздец-то
guest6 04.05.2021 15:03 # 0
MAKAKA 05.05.2021 15:08 # 0
Потому пихать в него сложные объекты лучше по ссылке/указателю ИМХО.
А напрямую сувать только тривиально копируемую мелочь типа структуры о двух полях
Жабаоёбы-скриптушки о такой хуйне не думают, лол.
Вернуть из функции массив объектов, каждый из которых представляет живое TCP соединение?
говно вопрос!
PolinaAksenova 05.05.2021 15:15 # 0
MAKAKA 05.05.2021 15:18 # 0
>мувабельные и копабельные объекты
А у листа какие требования?
Ладно, я научился читать:
T must meet the requirements of CopyAssignable and CopyConstructible.
PolinaAksenova 05.05.2021 15:20 # 0
У листа вообще только https://en.cppreference.com/w/cpp/named_req/Erasable, а остальные появляются по мере использования.
MAKAKA 05.05.2021 15:23 # 0
guest6 05.05.2021 15:21 # 0
MAKAKA 05.05.2021 15:24 # 0
Soul_re@ver 05.05.2021 15:26 # 0
bormand 05.05.2021 15:34 # 0
А ты считай, что std::move и мув-конструкторы -- это такая оптимизация, которая может и не примениться. Как RVO/NRVO.
Жить станет намного легче. И сразу понятно будет, когда надо вилкой чистить самому, а когда и так сойдёт.
Ну т.е. ты вполне можешь кидать invalid state из методов мувнутого объекта. С тем же успехом ты их можешь кинуть (и скорее всего кидаешь?) и из сконструированного по-умолчанию. Т.к. он тоже в не особо юзабельном состоянии.
j123123 05.05.2021 15:42 # 0
У меня в Си нет той хуйни, из-за которой такая оптимизация могла бы понадобиться. Именно поэтому я за Си.
MAKAKA 05.05.2021 15:46 # 0
j123123 05.05.2021 15:48 # 0
MAKAKA 05.05.2021 15:52 # 0
Вполне же есть, и означает он как раз кусочек памяти
j123123 05.05.2021 15:53 # 0
MAKAKA 05.05.2021 15:57 # 0
В сишке у тебя есть объект int из 8 байт, и ты его туда-сюда копируешь.
А при копировании ООП объекта будут еще коснтрукторы/деструкторы вызываться
Овнершип в сишке тоже есть, на самом деле: если ты сделал malloc, то ты точно знаешь, когда нужно сделать free
зы:
object: region of data storage in the execution environment, the contents of which can represent values
(ANSI C)
j123123 05.05.2021 16:14 # 0
Это не овнершип, это уже в голове программиста должно быть, что что-то где-то надо освободить. А можно и не освобождать, если это какая-то примитивная программа, которая допустим конвертит png в jpg используя какие-то либы, и потом завершается. ОСь сама приберет.
guest6 05.05.2021 16:17 # 0
Soul_re@ver 05.05.2021 16:17 # +2
*Грустные звуки embedded систем*
Хотя в них и динамического выделения памяти обычно нет.
j123123 05.05.2021 16:20 # 0
MAKAKA 05.05.2021 16:28 # 0
bormand 05.05.2021 16:32 # 0
Программа единственная, задач может быть много. И некоторые исполняются очень редко и не одновременно (обновление какое-нибудь, отправка данных и т.п.).
Но это скорее оверлейки чем процессы.
j123123 05.05.2021 16:33 # 0
Железка может уметь много чего делать, и ей может быть не нужно делать это одновременно (и памяти на одновременное делание всего у нее тоже нет). Поэтому железка может выделять память под хуйню№1, сделать хуйню№1, освободить память, выделить память под хуйню№2, сделать хуйню№2, освободить память. И эти хуйни№x может быть много, некоторые не сильно жрущие оперативку хуйни могут вполне работать одновременно, и они могут быть заранее неизвестны т.е. загружаться с внешнего флеш-накопителя или по блютузу какому-то скачиваться и устанавливаться, если это какая-то IoT-хуита. Так что для каких-то задач это вполне себе пригождается.
MAKAKA 05.05.2021 16:19 # 0
В крестах ты тоже можешь вручную это хендлить.
Тащемто кресты же это как раз про то, чтоб автоматически делать то, что сишник делает вручную.
j123123 05.05.2021 16:23 # 0
В крестах через эту вашу RAII-хуйню можно далеко не все, что можно руками. И RAII это не какая-то мегауниверсальная хуйня на все случаи, это просто еще один способ управлять ресурсами. См. https://govnokod.ru/27175#comment624086
MAKAKA 05.05.2021 16:27 # 0
>Допустим можно освобождать ресурсы в отдельном треде для освобождения ресурсов, и делать это во время простоев
Не изобрети случайно ГЦ, пожалуйста
Soul_re@ver 05.05.2021 16:35 # 0
bormand 05.05.2021 15:48 # 0
j123123 05.05.2021 15:49 # 0
MAKAKA 05.05.2021 15:54 # 0
Кстати, почему в "си" нельзя скопировать массив присваиваением?
Нельзя же?
bormand 05.05.2021 15:57 # 0
Из-за автокаста в поинтер.
Массивы существуют только как структура данных, а любое обращение к ним превращается в работу с поинтерами. Ну кроме sizeof.
Soul_re@ver 05.05.2021 15:59 # 0
j123123 05.05.2021 15:59 # 0
(но надо учесть всякую питушню с alingment и strict aliasing так что могут потребоваться доп. атрибуты)
bormand 05.05.2021 16:01 # 0
Но это будет UB? Это же не структуры с одинаковым началом и не поля юниона.
j123123 05.05.2021 16:06 # 0
Думаю тут надо __attribute__ ((aligned (1), packed, may_alias)). Тогда UB не будет.
PolinaAksenova 05.05.2021 16:49 # 0
И эти люди нядовольны std::move()!
MAKAKA 05.05.2021 16:02 # 0
Почему было их не копировать как обычные структуры?
Если я хочу передать массив в функцию по указателю, ну и писал бы &petuh или &petuh[0], не знаю.
Вроде это сделали по аналогии с каким-то древним япом
MAuCKuu_nemyx 04.05.2021 11:03 # −1
В минимальной версии и без него достаточно. Оно ж просто не скомпилируется.
ASD_77 04.05.2021 19:29 # 0
JloJle4Ka 04.05.2021 19:30 # 0
Soul_re@ver 04.05.2021 19:30 # 0
3_dar 05.05.2021 12:46 # +3
Ну как?
bormand 05.05.2021 12:55 # +1
Какой багор ))) А не, норм, тот конст внутри T.
guest6 05.05.2021 12:57 # 0
bormand 05.05.2021 13:08 # +1
JloJle4Ka 05.05.2021 13:10 # 0
Константный указатель на тип Т.
PolinaAksenova 05.05.2021 12:56 # +1
~SharedPtr() noexcept(noexcept(destroy()))
void destroy() noexcept(noexcept(delete std::declval<T*>()))
SharedPtr(SharedPtr&& other) noexcept // move-конструкторы и move-операторы присваивания должны быть noexcept
_PHP_ 05.05.2021 13:01 # +2
bormand 05.05.2021 12:59 # +1
PolinaAksenova 05.05.2021 13:07 # +2
bormand 05.05.2021 13:31 # 0
В самом shared_ptr и его Ref никаких гонок, по идее, нет, т.е. хватило бы relaxed'а.
Но что делать с delete value? Сослаться на то, что клиент сам своё говно синхронизировать обязан?
Soul_re@ver 05.05.2021 13:40 # +2
j123123 05.05.2021 18:04 # +2
PolinaAksenova 05.05.2021 13:44 # +1
JloJle4Ka 05.05.2021 13:02 # 0
Та зачем ref копьём проткнул? (((
Я бы лучше скобочки поставил, мало ли что.
А я боюсь так делать в крестах, у меня постоянно конпелятор ругается на подобное.
_PHP_ 05.05.2021 13:04 # +1
uwu
> А я боюсь так делать в крестах, у меня постоянно конпелятор ругается на подобное.
owo
bormand 05.05.2021 13:05 # +2
Ну да, очень легко позвать что-то виртуальное и напороться на UB с pure virtual call.
JloJle4Ka 05.05.2021 13:08 # 0
bormand 05.05.2021 13:10 # +2
Если конпелятор что-то скажет -- эт хуйня, чего тут бояться... Но он скорее промолчит и вызовет метод родителя вместо твоего. Особенно забавно, когда он НЕ абстрактный и прога сразу не падает.
Soul_re@ver 05.05.2021 13:34 # +2
Soul_re@ver 05.05.2021 13:11 # +2
Дурно пахнущая пессимизация. Ненужное сравнение, кторое сработает дай бог раз за 1000 использований.
Хотя в данном случае, если вдруг атомики оказались не lock-free, то возможно будет быстрее, чем стандартная альтернатива.
guest6 05.05.2021 13:23 # 0
bormand 05.05.2021 13:26 # +1
guest6 05.05.2021 13:29 # 0
bormand 05.05.2021 13:33 # +1
Soul_re@ver 05.05.2021 13:32 # +2
К тому же в том коде нет strong exception safety. Утечек нет, но если что-то пойдёт не так при уничтожении старого значения при присваивании, то у тебя попортится старое значение, а присваивания не произойдёт. Ну и перемещающего присваивания нет.
Во-первых ни один подход — не серебрянная пуля, об этом следует помнить. Иногда решение, которое прекрасно работало сотни раз, оказывается субоптимальным.
Ну а во вторых, вот как может выглядеть оператор копирующего/перемещающего присваивания.
Реализацию swap оставляю на самостоятельное изучение.
Soul_re@ver 05.05.2021 13:37 # +3
PolinaAksenova 05.05.2021 13:39 # +3
bormand 05.05.2021 13:43 # +1
Soul_re@ver 05.05.2021 13:45 # +1
bormand 05.05.2021 13:48 # 0
Soul_re@ver 05.05.2021 13:49 # +1
bormand 05.05.2021 13:50 # +1
Мой объект просто мувается в аргумент, а старое значение разрушается на выходе из оператора.
PolinaAksenova 05.05.2021 13:50 # 0
Soul_re@ver 06.05.2021 10:47 # +1
j123123 07.05.2021 14:13 # +1
bormand 07.05.2021 14:21 # +1
Когда-нибудь и я уйду в монахи... Но пока кресты вполне устраивают.
j123123 07.05.2021 14:28 # 0
https://habr.com/ru/post/497114/
> Кто я такой? Я программист на плюсах. Я пишу код на плюсах две трети жизни. Это действительно стало огромной частью моей самоидентификации. Почему я претендую на синиора? Потому что я успел отстрелить себе миллион ног и натаскать свою нейросеть в черепушке определять, какая нога отстрелена на этот раз, по отсвету дульной вспышки. Потому что все интервью, касающиеся языка, я проходил, как тут говорят, with flying colors. Потому что я могу даже не готовиться к интервью, и всё равно его пройду. Потому что я могу показать особо интересные куски кода на гитхабе, и для меня скипнут как минимум телефонное интервью, а иногда скипали и техническое собеседование, разговаривая только о жизни или в лучшем случае о дизайне систем, релевантных для места работы.
j123123 07.05.2021 14:29 # 0
MAKAKA 07.05.2021 14:49 # +1
(у автора конечно, не у тебя)
j123123 07.05.2021 14:49 # 0
Одни знания и навыки описывают некие фундаментальные вещи, ну например знания химии. У тебя не будет ситуации, когда твои знания по химии станут внезапно совсем не актуальны. Не, ну можно конечно представить что-то, например если тебя аниме-девочки заберут в альтернативную вселенную, где будут действовать другие законы физики, химии и прочее, но это уже на гране фантастики, понимаешь? В программировании такие знания/навыки это например умение писать всякие алгоритмы, ну допустим нормальный программист должен без проблем набросать по памяти какой-нибудь двусвязный список. В эту же категорию идет умение использовать циклы, рекурсию, оценивать временную сложность алгоритмов. Такая питушня не прибита гвоздями к говноязыку, она вполне кроссплатформенная в этом смысле
А есть знания, которые о какой-то созданной человеке хуитени, в которых ничего фундаментально-значимого нет. Типичный пример - инструкция использования какого-то сложного прибора с кучей кнопочек и переключателей. И если тебе в какой-то момент дадут другой прибор от другого производителя с другими кнопочками и переключателями, твои задротские навыки использования того прибора окажутся нахуй не нужны, понимаешь? Вот знания крестоговна - это как раз из этой области.
MAKAKA 07.05.2021 14:51 # 0
j123123 07.05.2021 14:52 # 0
MAKAKA 07.05.2021 15:03 # 0
Не понимаю, зачем о них волноваться
j123123 07.05.2021 15:19 # 0
Ну если сопоставить размер книги по крестам от Страуструпа с размером книги Танненбаума по ОС... вполне сопоставимы.
Видимо забивать мозг этой крестохуйней нужно в сопоставимой степени, чтобы считаться сеньор-крестоговно-девелопером
MAKAKA 07.05.2021 15:23 # 0
Почему мы не слышим таких статей от джава программистов?
bormand 07.05.2021 15:36 # 0
MAKAKA 07.05.2021 15:43 # 0
У джавы довольно развесистая стандартная либлиотека, особенно если включить в неё JavaEE. Может быть книжка большая потому.
bormand 07.05.2021 15:02 # 0
Да, это сейчас популярно. Но вангую что лет через 50-100 это всё уйдёт на помойку, как туда ушли знания об аналоговых ЭВМ.
З.Ы. Пригодится ли тебе умение писать циклы и рекурсию для вычислений на FPGA? Не думаю, мне первое время даже мешало.
j123123 07.05.2021 15:07 # 0
Циклы тоже можно и без ЭВМ. Например, если тебе надо забить 200 гвоздей в ряд с расстоянием в 1 см между каждым, можно представить это себе как цикл, забить гвоздь по смещению 0 см влево относительно этой координаты, потом забить гвоздь по смещению 1 см влево относительно этой координаты, и так далее.
Циклы и рекурсия ближе к фундаментальной математике, чем к каким-то цифровым машинам. Они и не на цифровых машинах могут.
j123123 07.05.2021 15:10 # 0
Ну если тебе надо экономить ячейки, и скорость не важна, вполне можно некую хрень саму на себя как-нибудь зациклить в схеме из логических элементов. Попробуй bigint умножение на FPGA реализовать для больших чисел.
bormand 07.05.2021 15:14 # 0
Но в коде это не выглядит как цикл! Умение писать циклы на традиционных языках тут вообще только мешает понять новую концепцию.
З.Ы. Это ближе к чему-то функциональному в духе map/reduce.
j123123 07.05.2021 15:15 # 0
Или можно хаскель взять какой-нибудь, там циклов тоже нет, и что?
MAKAKA 07.05.2021 15:17 # 0
bormand 07.05.2021 15:22 # +1
Это факт, вон в факторио у программистов всегда первый вопрос "а как мне запилить if или for на кобенаторах?" Ну т.е. если ты всю жизнь мыслишь концепциями циклов и условий, то очень сложно принять что-то новое.
MAKAKA 07.05.2021 15:25 # 0
Видел такое
Хотя императивщину, наверное, проще понять: всё так наш мир императивен
CHayT 07.05.2021 15:28 # 0
Так Эрланг появился. Джо Армстронгу (RIP) тоже подобный анскилл не понравился.
bormand 07.05.2021 15:28 # 0
Скажи это электронам и прочим фотонам.
MAKAKA 07.05.2021 15:30 # 0
gologub 07.05.2021 16:14 # 0
CHayT 07.05.2021 15:15 # 0
bormand 07.05.2021 15:18 # 0
Выдуманная человеком хуйня, как и вся математика.
Не факт, что какие-нибудь иноплане-тянки с альфы Центавра придут точно к таким же концепциям, даже если физика у них та же самая.
j123123 07.05.2021 15:30 # 0
Та же химия/физика описывается во многих местах через рекурсию, вполне естественным образом. Всякие динамические системы там с диффурами есть. Допустим состояние системы в момент времени t2 зависит от состояния системы в момент времени t1 и у нас есть фукнция отображения state(t2) := do_transform(state(t1)) и тут кстати можно попробовать найти неподвижную точку, когда некий state(x-1) == do_transform(state(x-1)) т.е. когда состояние системы не меняется от времени.
Физика нашей реальности такой питушней хорошо описывается, и поэтому совершенно естественно, что такой формализм будет придуман для ее описания
Ты же не будешь утверждать, что такие инопланетянки могут построить космические корабли, но не будут знать, что 1+1=2, верно?
bormand 07.05.2021 15:33 # 0
j123123 07.05.2021 15:34 # 0
CHayT 07.05.2021 15:35 # 0
CHayT 07.05.2021 15:44 # +1
Если законы физики у инопланетянок такие же, то и эволюционный отбор у них работает примерно так же, т.е. стремится на всём, включая размер мозга, сэкономить.
gologub 07.05.2021 16:04 # 0
PolinaAksenova 05.05.2021 13:46 # +1
JloJle4Ka 05.05.2021 13:42 # 0
ASD_77 05.05.2021 20:39 # 0
PolinaAksenova 05.05.2021 20:40 # +2
guest6 06.05.2021 00:41 # +1
Пиздец (( Пока по твоей ссылке не понял что это и как это хуетой пользоваться.
MAKAKA 06.05.2021 01:51 # +3
Кнопка знает про слушателя, а слушатель -- про кнопку.
Если у них обоих будет друг на друга умный указатель, то они никогда не удалятся, бо будут держаться друг за друга как слипшиеся какашки.
Для решения этой проблемы в ЯП с RC есть weak ссылы/указатели. Они буквально означают "пусть тот, на кого у меня ссылка , умрет. Мне похуй. Я как-нить переживу".
У кнопки на слушателя shared_ptr (а больше ни у кого). Это значит, что когда кнопка умрет, должен будет умереть и слушатель.
У слушателя на кнопку weak_ptr. Перед обращением к нему слушатель проверяет её метод "expired". Если она expired, то ссылка невалидна.
Ключом к понимаю weak_ptr является вот этот метод:
https://en.cppreference.com/w/cpp/memory/weak_ptr/expired
MAKAKA 05.05.2021 20:45 # 0
Вот пример из Swift
https://www.programmersought.com/article/1272854504/
j123123 05.05.2021 21:53 # 0
Хуёво она решена (если это вообще можно назвать решением).
См. https://govnokod.ru/27340#comment621591
MAKAKA 05.05.2021 21:55 # +1
>то мы еще должны заранее знать
да, ты должен всегда понимать кто на что ссылается. В некоторых средах на это есть гайдлайны.
Не хочется руками разгребать циклы -- кушайте ГЦ. Или есть еще более красивые варианты?
j123123 05.05.2021 21:59 # +2
А если у меня просто граф из какой-то хуйни, который хуй пойми как перестраивается в процессе работы, и если я там буду придумывать, какая из хуитеней на что когда и как указывает как weak_ptr, а какая как обычный shared_ptr то это просто сраный пиздец получится. Придумывать еще какую-то ебанутую логику, что если такой-то shared_ptr переткнулся с той дрисни на ту дрисню в каком-то говнографе, то вот эта shared_ptr дрисня будет уже weak_ptr. Это будет просто адовый сраный пиздец, и работать это будет вероятно даже медленней, чем GC т.к. надо по этим говносвязям бегать и переставлять weak_ptr на shared_ptr и наоборот.
Так что в целом эта проблема, имхо, никак не решена. Заменить этой хуйней обычный GC тупо нельзя
MAKAKA 05.05.2021 22:07 # 0
Если в твоем графе тебе понадобится не только память чистить, но и закрывать ресурсы, то тебе всё равно придется строить граф на бумажечке, и понять, где папа, а где сын.
Если из всего множества программ выкинуть те, в которых:
* Граф очевиден
* Граф всё равно нужно понимать чтобы освобождать ресурсы
* Можно вообще ничего не освобождать, а сразу выделить память, и жить с ней до конца програмы
..то останутся случаи, для которых хорошо подходит GC. Их не так и много
j123123 05.05.2021 22:24 # 0
Суть там в https://en.wikipedia.org/wiki/Hypergraph
bormand 07.05.2021 14:28 # 0
MAKAKA 07.05.2021 14:53 # 0
Если ты будешь делать вид, что память тебя не интересует, то она утечет. Именно потому в жабке тоже есть SoftReference и WeakReference. Абстракция протекла, и даже тупой жабаобезъяне пришлось понимать , что куча -- не бездонная корова, чтоб туда срать
CHayT 07.05.2021 14:58 # +3