Название: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 02, 2017, 10:04 Привет, друзья!
Прошу помочь разобраться, почему следующий код не верен. Код По идеи в правой части список инициализации с xvalue. Почему компиляторы требуют от меня реализации копирования? Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Racheengel от Февраль 02, 2017, 11:53 Наверное потому, что помещение в std::map - это копирование?
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 02, 2017, 13:41 Конструкторы std::map (http://www.cplusplus.com/reference/map/map/map/).
Конструктор (5): Цитировать (5) initializer list constructor Constructs a container with a copy of each of the elements in il. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 02, 2017, 14:09 Конструкторы std::map (http://www.cplusplus.com/reference/map/map/map/). Туда-то я как-то и не догадался первым делом посмотреть. Спасибо.Конструктор (5): Цитировать (5) initializer list constructor Constructs a container with a copy of each of the elements in il. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 02, 2017, 15:24 Ради интереса потом можете попробовать засунуть unique_ptr<A> в QMap ;).
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 02, 2017, 16:23 Не, всё та же проблема с копированием unique_ptr
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 02, 2017, 16:25 Подглядел где-то, что shared_ptr подойдёт для моих нужд.
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 02, 2017, 16:29 Кстати, быть может это будет и правильнее с точки зрения проектирования. Ведь мне необходимо в некоторых методах возвращать указатель на объект, так пусть он и будет завёрнут в shared_ptr.
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 02, 2017, 17:02 Ведь мне необходимо в некоторых методах возвращать указатель на объект, так пусть он и будет завёрнут в shared_ptr. Это плохая идея - возвращать голый указатель на объект под управлением умного указателя. Нужно стараться обходиться unique_ptr, shared_ptr, weak_ptr и ссылками на объект. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Igors от Февраль 02, 2017, 17:20 Допустим желанная мапа <int, unique_ptr> создана. Как она должна работать7
Код: auto val = theMap.value(1); // и после этого мапа хранит пустой указатель по ключу 1 Кстати, быть может это будет и правильнее с точки зрения проектирования. Ведь мне необходимо в некоторых методах возвращать указатель на объект, так пусть он и будет завёрнут в shared_ptr. Это часто хорошо, но не всегда, во всяком случае это действие не безобидноНазвание: Re: std::map<..., unique_ptr> инициализация Отправлено: Авварон от Февраль 02, 2017, 23:21 Допустим желанная мапа <int, unique_ptr> создана. Как она должна работать7 Код: auto val = theMap.value(1); // и после этого мапа хранит пустой указатель по ключу 1 У std::map нет метода value. operator[] и at() возвращают ссылку. Вы вот так хвалитесь незнанием букваря, а лучше бы поучили стандартную библиотеку, там многое сделано очень грамотно и обоснованно для кучи разных юзкейзов (скорость, exception-safety и тп) Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Авварон от Февраль 02, 2017, 23:40 Ради интереса потом можете попробовать засунуть unique_ptr<A> в QMap ;). Забавно, что корни этой проблемы лежат не в лени кутешников, а в... фанфары... copy-on-write. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 03, 2017, 13:36 Забавно, что корни этой проблемы лежат не в лени кутешников, а в... фанфары... copy-on-write. Точно :). Ещё стоит отметить любовь кутешников к смешиванию нескольких функциональностей/техник в одном флаконе, без возможности выбора. Implicit Sharing в контейнерах штука может и полезная, но, как выясняется, не всегда. Такие контейнеры не могут хранить уникальные объекты, что сужает область их применения. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Igors от Февраль 03, 2017, 14:30 У std::map нет метода value. И что, получив такую ссылку я должен все время следить не скопирована ли она? operator[] и at() возвращают ссылку. Такие контейнеры не могут хранить уникальные объекты, что сужает область их применения. А что (какой ф-ционал) хотелось получить? И что здесь понимается под уникальностью? Только один владеет? (unique_ptr). Тогда зачем помещать его в контейнер - ведь это подразумевает обращение к этому контейнеру.Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 03, 2017, 14:42 А что (какой ф-ционал) хотелось получить? И что здесь понимается под уникальностью? Только один владеет? (unique_ptr). Тогда зачем помещать его в контейнер - ведь это подразумевает обращение к этому контейнеру. А зачем вообще нужен unique_ptr? Функционал такой же, как при использовании unique_ptr, только с возможностью хранить несколько объектов, а не один. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Авварон от Февраль 03, 2017, 14:58 И что, получив такую ссылку я должен все время следить не скопирована ли она? Эм, компилятор выдаст ошибку при попытке скопировать, на то он и юник. А что (какой ф-ционал) хотелось получить? И что здесь понимается под уникальностью? Только один владеет? (unique_ptr). Тогда зачем помещать его в контейнер - ведь это подразумевает обращение к этому контейнеру. Код: class Node Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Igors от Февраль 03, 2017, 15:23 Код: class Node Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Авварон от Февраль 03, 2017, 15:41 Смешивать "голых с умными" совсем нехорошо. Но даже если и так - какую же выгоду мы поимели с unique_ptr? Вообще часто замечал что вумные указатели лепятся без каких-либо оснований, типа "это круто/грамотно" :) 1) Не надо писать руками qDeleteAll(). 2) Exception-safety. Код: _children.push_back(new Node); // oooops! Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 03, 2017, 16:27 Ведь мне необходимо в некоторых методах возвращать указатель на объект, так пусть он и будет завёрнут в shared_ptr. Это плохая идея - возвращать голый указатель на объект под управлением умного указателя. Нужно стараться обходиться unique_ptr, shared_ptr, weak_ptr и ссылками на объект. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 03, 2017, 16:35 Код: class Node Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Авварон от Февраль 03, 2017, 16:52 Критикуешь - предлагай. Как вернуть указатель на потомка? Ну в данном примере можно и ссылку. Или указатель. Вообще, то что там под "капотом" юник волновать никого не должно - либо мы, когда получаем указатель, имеем овнершип (и должны удалять), либо не имеем. Ссылка явно говорит о том, что не имеем. Возврат шаред/юник - наоборот. Возврат голого указателя заставляет читать документацию (привет, Qt). Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 03, 2017, 16:59 Встречал рекомендацию детей хранить как weak, а их родителей как shared.
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ssoft от Февраль 03, 2017, 17:22 Критикуешь - предлагай. Как вернуть указатель на потомка? А не нужно с указателями работать, нужно с ссылками - обычные или std::reference_wrapper, а указатели глубокоо внутри держать. Со ссылкой так вольно уже не позабавишься), придется как минимум преобразовывать. А вообще, умные указатели unique_ptr и shared_ptr в простейшем виде реализуют понятие агрегации - обобщенной и композитной. Но с ними должны быть связаны и ассоциации, которые не реализуют агрегацию в принципе. Такого рода ассоциации могут быть реализованы разными способами. Если повсеместно в явном виде в API используются unique_ptr и shared_ptr, то естественно тогда и голые указатели использовать (для shared реализован еще и безопасный weak). Но будьте готовы, что сам экземпляр объекта можно будет "украсть" (std::move в помощь). Поэтому лучше всего умные указатели скрывать где-то внутри, а для доступа к данным и реализаций ассоциаций использовать всякого рода ссылки. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 03, 2017, 18:18 Если упростить, то должна быть возможность владеть объектом, и ссылаться на него (в определённый момент времени получить доступ к объекту, не владея им). unique_ptr и shared_ptr владеют объектом, а weak_ptr ссылается на него. Для unique_ptr нет "ссылающегося" умного указателя (аналога weak), остаются только голый указатель и ссылка, что совсем не умно и не безопасно. Так что в текущих std реалиях для организации владения и связей объектов безопасно можно использовать связку shared_ptr/weak_ptr.
При использовании shared_ptr голый указатель можно заменить на weak_ptr. Какой алгоритм работы с голым указателем? Код
Причём проверка ( object_ptr != nullptr ) не даёт особых гарантий. Объект может быть удалён, а указатель будет продолжать указывать на мусор. С использованием weak_ptr алгоритм аналогичный: Код
В этом случае гарантий больше. Во-первых, можно проверить, что объект существует на момент обращения к нему. Во-вторых, время жизни объекта продлевается на время обращения к нему (на время существования object_guard). Даже если все внешние shared_ptr< SomeObject > удалятся, метод SomeClass::someMethod сможет нормально завершить работу с переданным объектом. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Igors от Февраль 03, 2017, 19:51 Код
В этом случае гарантий больше. Во-первых, можно проверить, что объект существует на момент обращения к нему. Во-вторых, время жизни объекта продлевается на время обращения к нему (на время существования object_guard). Даже если все внешние shared_ptr< SomeObject > удалятся, метод SomeClass::someMethod сможет нормально завершить работу с переданным объектом. Код Не всегда во второй ветке можно ничего не делать. А объявлять m_object_shared (вместо m_object_weak) - свои минусы, выходит как бы "2 владельца", изменив одного надо перезарядить и второго Update: и вообще стоит ли (упорно) добиваться чтобы абсолютно все указатели были так или иначе вумными? Мое мнение - нет, не стоит, лучше пусть небольшая часть. Но если уж вумный - не должно быть таких голых Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Old от Февраль 04, 2017, 17:48 Update: и вообще стоит ли (упорно) добиваться чтобы абсолютно все указатели были так или иначе вумными? Мое мнение - нет, не стоит, лучше пусть небольшая часть. Но если уж вумный - не должно быть таких голых Конечно стоит. Именно все указатели должны быть умными, в 21 веке то. А если используешь умные указатели, то о голых нужно полностью забыть (или извращения в коде неизбежны).К сожалению legacy Qt не позволяет это сделать, но к радости программирование не ограничивается только Qt. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 05, 2017, 00:32 Цитировать Language is called c++ and not ++c because the language is improved but many people use it as C. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Igors от Февраль 05, 2017, 12:59 Код Вроде бы все норм. Теперь не надо инициализировать m_data в конструкторе и удалять в деструкторе. И он может быть нулевым, поэтому умный указатель, а не просто член SomeData. Но вот неясно, действительно ли мы собирались его шарить? Увидев такое объявление - надо ли иметь ввиду что неск SomeClass юзают один m_data? Или это так просто, "умный указатель лучше"? Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Old от Февраль 05, 2017, 13:23 Увидев такое объявление - надо ли иметь ввиду что неск SomeClass юзают один m_data? Или это так просто, "умный указатель лучше"? А для такого объявления ваши вопросы уже не актуальны? :)Код
А если еще такое, то без документации (просмотра исходников) не понять, а что это за указатель и кто должен удалять данные по этому указателю. Код
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ssoft от Февраль 07, 2017, 19:10 Если упростить, то должна быть возможность владеть объектом, и ссылаться на него (в определённый момент времени получить доступ к объекту, не владея им). unique_ptr и shared_ptr владеют объектом, а weak_ptr ссылается на него. Для unique_ptr нет "ссылающегося" умного указателя (аналога weak), остаются только голый указатель и ссылка, что совсем не умно и не безопасно. Так что в текущих std реалиях для организации владения и связей объектов безопасно можно использовать связку shared_ptr/weak_ptr. Если говорить строго, то владение, ссылание - это все отношения ассоциаций, а shared_ptr/weak_ptr, unique_ptr и любой my_ptr - все это инструменты управления временем жизни экземпляра объекта с определенными свойствами, с помощью которых уже могут быть реализованы любые ассоциативные связи. В зависимости от конкретного случая вполне оправдано использование инструментов в любом сочетании shared/weak, shared/raw, unique/raw (raw - "голый" указатель), shared/my_any, так как все они имеют разную стоимость своего использования. Нужна потокобезопасность - считайте ссылки shared/weak, нужна скорость - используйте unique/raw и т.д., валидность указателей обеспечивайте другим способом (логикой использования). Не обязательно shared/weak инструментарий должен реализовывать только обобщенное владение, на этой основе вполне логично реализуется и уникальное владение, и неявно обобщенное. В этом же ключе - нет никакого смысла реализовывать weak для unique, так как реализация такого unique должна повторить shared (на случай продления времени жизни экземпляру с помощью guard в примере). Для практического применения на первый план выходит реализация конкретной ассоциативной связи, а способ ее внутренней реализации может (и должен) быть скрыт глубоко внутри. Ассоциативная связь подразумевает некоторое представление самого экземпляра объекта, в простейшем случае псевдонима (ссылки). И указатели во всем их разнообразии все же не являются представлением экземпляра, таким представлением являются разнообразные умные ссылки - представители объекта с разными свойствами. К сожалению механизм умных ссылок вообще почти не продуман в стандарте, появилась только простейшая реализация в виде std::reference_wrapper, но сам принцип их построения понятен - использование паттерна Adapter (Wrapper). В соседней теме про корову есть наброски пары реализаций ImplicitWrapper. :) В любом случае, соблазн использовать raw указатели всегда очень велик, особенно на начальном этапе при непродуманной архитектуре - потом выясним ху из ху. :D Использование внятных абстракций типа wrapper, существенно повышают качество кода и понятность модели, но требуют наличия взаимодействия достаточно большого количества сущностей реализующих - ассоциации, продление времени жизни, доступ на чтение, доступ на запись и др. ;) Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 07, 2017, 20:21 Использование внятных абстракций типа wrapper, существенно повышают качество кода и понятность модели, но требуют наличия взаимодействия достаточно большого количества сущностей реализующих - ассоциации, продление времени жизни, доступ на чтение, доступ на запись и др. ;) Ещё хорошо продуманные wrapper не позволяют ерунду в коде писать :). По крайней мере всячески этому сопротивляются, и заставляют думать, где какое владение использовать и какие типы связей должны быть между объектами на уровне модели. И подход "скомпились уже и отстань от меня", как можно было писать в случае с голыми указателями, с wrapper уже не прокатывает :). А текущие unique_ptr, shared_ptr, weak_ptr зачастую используются как некий частный случай сборщика мусора и не более. Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Old от Февраль 08, 2017, 00:58 В зависимости от конкретного случая вполне оправдано использование инструментов в любом сочетании shared/raw, unique/raw Никогда не оправдано. Только вернули raw - полностью потеряли контроль над объектом.shared/my_any Это вообще как?Название: Re: std::map<..., unique_ptr> инициализация Отправлено: __Heaven__ от Февраль 08, 2017, 07:30 Подозреваю, что так
Код
Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Igors от Февраль 08, 2017, 08:26 Ещё хорошо продуманные wrapper не позволяют ерунду в коде писать :). По крайней мере всячески этому сопротивляются, и заставляют думать, где какое владение использовать и какие типы связей должны быть между объектами на уровне модели. И подход "скомпились уже и отстань от меня", как можно было писать в случае с голыми указателями, с wrapper уже не прокатывает :). Так-то оно так, но для объявления. А если указатель подается в ф-цию/метод, то в подавляющем большинстве случаев никакой умности не требуется. СравнимКод Теперь (2-я строка) ф-ция не сможет удалить данные! И гарантируется что data будет жить даже если вызывающий удален! (актуально при multi-threading). Не очень-то веские причины/резоны. Выходит из заявления shared_ptr ничего по существу не следует, и на него можно не обращать внимания. Зачем тогда заявлять? Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 08, 2017, 12:51 Так-то оно так, но для объявления. А если указатель подается в ф-цию/метод, то в подавляющем большинстве случаев никакой умности не требуется. Сравним Код Теперь (2-я строка) ф-ция не сможет удалить данные! И гарантируется что data будет жить даже если вызывающий удален! (актуально при multi-threading). Не очень-то веские причины/резоны. Выходит из заявления shared_ptr ничего по существу не следует, и на него можно не обращать внимания. Зачем тогда заявлять? Как раз и следует: Теперь (2-я строка) ф-ция не сможет удалить данные! И гарантируется что data будет жить даже если вызывающий удален! (актуально при multi-threading). И это достаточно веские резоны. Если на этапе проектирования решено, что объект находится в совместном владении, то в общем случае не известно, когда и кем он будет удалён. Может вызывающий код не хочет, чтоб какая-то левая функция удалила объект без его ведома? Поэтому и передаёт другим в пользование shared_ptr. Чтобы выразить факт того, что функция DoSomething гарантировано удалит объект (или возьмёт время его жизни в своё единоличное управление), то в своей сигнатуре она должна использовать unique_ptr. И вызывающий код туда ничего кроме unique_ptr передать не сможет. Он должен передать владение объектом в функцию с помощью move-семантики (http://stackoverflow.com/questions/3106110/what-are-move-semantics). Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ssoft от Февраль 08, 2017, 15:30 shared/raw, unique/raw Никогда не оправдано. Только вернули raw - полностью потеряли контроль над объектом.Под контролем здесь скорее всего подразумевается управление временем жизни экземпляра объекта. То есть простой механизм сбора мусора? Ассоциативные связи агрегации (shared/composite) обеспечивают управление временем жизни экземпляра, а вот другие виды ассоциативных связей совершенно не обязаны это делать. Как задать ассоциативную связь отличную от агрегации для unique_ptr, кроме как raw? Обычная ссылка не подойдет, так как во-первых ссылка и указатель сущности разной природы, а во-вторых ссылка не может быть изменена в дальнейшем. Для shared в критических местах тоже лишний раз счетчик трогать нежелательно. Если есть алгоритмическая гарантия того, что экземпляр не удалится во время выполнения (например, заранее заведен guard), то вполне резонно использовать и raw указатель. Другое дело не рекомендовать использовать сочетания shared/raw, а рекомендовать shared/weak, где это возможно. A shared/raw оставить для продвинутого использования, с учетом того что имеется понимание опасности того, что это за собой влечет. Для того чтобы совсем отказаться от raw указателей не хватает еще достаточного количества сущностей в стандарте. Это может быть реализовано как угодно). Можно и свой огород налепить, например, логировать операции с указателем, считать какую-нибудь статистику и т.п., был бы прикладной смысл. Кстати, под shaed не обязательно только shared_ptr понимать. ;D Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Old от Февраль 08, 2017, 15:52 Под контролем здесь скорее всего подразумевается управление временем жизни экземпляра объекта. То есть простой механизм сбора мусора? Нет. Я говорю о методах класса, которые возвращают raw-указатель. При возврате умного указателя по нему можно предположить, что с объектом может произойти и что с ним можно делать. С raw указателем это не так. Обычная ссылка не подойдет, так как во-первых ссылка и указатель сущности разной природы, а во-вторых ссылка не может быть изменена в дальнейшем. Что значит "сущности разной природы"? Чем это ссылки не подходят?И что значит "ссылка не может быть изменена в дальнейшем"? Храните указатель, а возвращайте ссылку. Часто этого достаточно. Сразу хочу отметить, я говорю про указатели отдаваемые наружу. Внутри некоего класса иногда можно использовать raw-указатели, но отдавать его наружу очень опасно (а c shared_ptr так вообще). Для того чтобы совсем отказаться от raw указателей не хватает еще достаточного количества сущностей в стандарте. Пишите свои. Используйте ссылки. Отказаться от raw-указателей можно было уже много лет назад. :)Это может быть реализовано как угодно). Можно и свой огород налепить, например, логировать операции с указателем, считать какую-нибудь статистику и т.п., был бы прикладной смысл. Кстати, под shaed не обязательно только shared_ptr понимать. ;D Ааа. А то у меня my_any ассоциировалось с boost::any. И я испугался. :)Название: Re: std::map<..., unique_ptr> инициализация Отправлено: Igors от Февраль 08, 2017, 16:05 Может вызывающий код не хочет, чтоб какая-то левая функция удалила объект без его ведома? Поэтому и передаёт другим в пользование shared_ptr. Чтобы выразить факт того, что функция DoSomething гарантировано удалит объект (или возьмёт время его жизни в своё единоличное управление), то в своей сигнатуре она должна использовать unique_ptr. И вызывающий код туда ничего кроме unique_ptr передать не сможет. Он должен передать владение объектом в функцию с помощью move-семантики (http://stackoverflow.com/questions/3106110/what-are-move-semantics). ПримерКод Это и так грубая ошибка/просмотр, оставляющая вызывающего с невалидным указателем. Если есть необходимость мочить указатель в ф-ции (достаточно редкий случай), то просто и хорошо Код
И это достаточно веские резоны. Если на этапе проектирования решено, что объект находится в совместном владении, Хорошо, допустим решено, но сколько данных реально шарится? Да %20 отсилы, как бы не меньшето в общем случае не известно, когда и кем он будет удалён. В подавляющем большинстве случаев - прекрасно известно. НапрКод Не вижу здесь ничего плохого. Написал в ф-ции delete - ну сам "злобный Буратино", в конце-концов мог и в самой ф-ции сделать get и delete. Время жизни - для ф-ции forever. Так от каких мифических угроз защищаемся? А вот утяжеление кода и, особенно, затруднение отладки - минусы очень ощутимые. Для того чтобы совсем отказаться от raw указателей не хватает еще достаточного количества сущностей в стандарте. Да, shared_ptr гораздо чаще лепится для "сборки мусора" (другого-то ничего нет), а не потому что действительно шаритсяНазвание: Re: std::map<..., unique_ptr> инициализация Отправлено: ssoft от Февраль 08, 2017, 16:38 Обычная ссылка не подойдет, так как во-первых ссылка и указатель сущности разной природы, а во-вторых ссылка не может быть изменена в дальнейшем. Что значит "сущности разной природы"? Чем это ссылки не подходят?И что значит "ссылка не может быть изменена в дальнейшем"? Храните указатель, а возвращайте ссылку. Часто этого достаточно. Об этом я как раз и писал раннее, что вместо указателей необходимо использовать различные виды умных ссылок (wrapper), простейшим из которых является std::reference_wrapper. Указатель в явном виде никогда не говорит о том какую конкретно ассоциацию он реализует (кроме unique возможно). Ссылка - это представитель объекта, псевдоним, для использующей стороны она выглядит как сам объект, указатель не выглядит как объект. Обычная ссылка - это Type & или const Type &, она не может быть изменена в дальнейшем. Сразу хочу отметить, я говорю про указатели отдаваемые наружу. Внутри некоего класса иногда можно использовать raw-указатели, но отдавать его наружу очень опасно (а c shared_ptr так вообще). Для того чтобы совсем отказаться от raw указателей не хватает еще достаточного количества сущностей в стандарте. Пишите свои. Используйте ссылки. Отказаться от raw-указателей можно было уже много лет назад. :)Вот свои и пишем ;D, и получаем очередной зоопарк решений. А при стыковке нескольких решений, да если еще и Qt приляпать, в ход идут добрые, старые и знакомые raw указатели. Так что не так-то просто от них совсем отказаться. ;) Название: Re: std::map<..., unique_ptr> инициализация Отправлено: ViTech от Февраль 08, 2017, 17:47 В подавляющем большинстве случаев - прекрасно известно. Напр Код Не вижу здесь ничего плохого. Написал в ф-ции delete - ну сам "злобный Буратино", в конце-концов мог и в самой ф-ции сделать get и delete. Время жизни - для ф-ции forever. Неизвестно. В С++ имея хоть какой-нибудь доступ к объекту можно его убить. Элементарно: Код
Никто и не пикнет. А кто вздумает const'ом защищаться, того const_cast'ом обезоружить ;D. Но за такое надо по голове очень сильно бить. И это другая история. Так от каких мифических угроз защищаемся? А вот утяжеление кода и, особенно, затруднение отладки - минусы очень ощутимые. Защищаемся от разыменования nullptr и обращения к убитым объектам. Управляем временем жизни объекта. И в сигнатуре функции, в типах входящих и возвращаемых параметрах, яснее сообщается, что можно делать с объектом, а что нельзя. И не надо использовать методы умных указателей, которые возвращают raw-указатели. Лучше вообще считать, что их нет( get() и им подобные). Нужны они в особых случаях и для сопряжения с legacy-кодом. |