Разное

Умные указатели c: Шпаргалка по использованию умных указателей в C++

Содержание

Умные указатели — The Rust Programming Language

Указатель — это общая концепция для переменной, которая содержит адрес на участок памяти. Этот адрес «относится к», или «указывает на» некоторые другие данные. Наиболее общая разновидность указателя в Rust — это ссылка, о которой вы узнали из Главы 4. Ссылки обозначаются символом & и заимствуют значение на которое они указывают. Они не имеют каких-либо специальных возможностей, кроме как ссылаться на данные. Кроме того, они не имеют никаких накладных расходов и являются тем указателем, который мы используем чаще всего.

Умные указатели с другой стороны, являются структурами данных, которые не только действуют как указатель, но также имеют дополнительные метаданные и дополнительные возможности. Концепция умных указателей не уникальна для Rust: умные указатели возникли в C ++ и существуют в других языках. В Rust есть разные умные указатели, определённые в стандартной библиотеке, которые обеспечивают функциональность выходящую за рамки ссылок. Одним из примеров, который мы рассмотрим в этой главе, является тип умного указателя reference counting (подсчёт ссылок). Этот указатель позволяет иметь несколько владельцев данных с помощью отслеживания количества владельцев и очистки данных, когда владельцев не осталось.

В Rust, который использует концепцию владения и заимствования, дополнительная разница между ссылками и умными указателями заключается в том, что ссылки являются указателями, которые только заимствуют данные; против того, что во многих случаях умные указатели владеют данными на которые они указывают.

Мы уже встречали несколько умных указателей в этой книге, таких как String и тип Vec<T> в главе 8, хотя мы не называли их умными указателями в тот момент. Оба этих типа считаются умными указателями, потому что они владеют некоторой областью памяти и позволяют ею манипулировать. У них также есть метаданные (например, их ёмкость) и дополнительные возможности или гарантии (например, String обеспечивает, что содержимое всегда будет действительными данными в кодировке UTF-8).

Умные указатели обычно реализуются с использованием структур. Характерной чертой, которая отличает умный указатель от обычной структуры является то, что для умных указателей реализованы типажи Deref и Drop. Типаж Deref позволяет экземпляру умной структуры указателя вести себя как ссылка, так что вы можете написать код работающий или со ссылками или с умными указателями. Типаж Drop позволяет настроить код запускаемый, когда экземпляр умного указателя выходит из области видимости. В этой главе мы обсудим оба типажа и продемонстрируем почему они важны для умных указателей.

Учитывая, что шаблон умный указатель является общим шаблоном проектирования часто используемым в Rust, эта глава не описывает все существующие умные указатели. Множество библиотек имеют свои умные указатели и вы также можете написать свои. Мы охватим наиболее распространённые умные указатели из стандартной библиотеки:

  • Box<T> для распределения значений в куче (памяти)
  • Rc<T> тип счётчика ссылок, который допускает множественное владение
  • Типы Ref<T> и RefMut<T>, доступ к которым осуществляется через тип RefCell<T>, который обеспечивает правила заимствования во время выполнения, вместо времени компиляции

Дополнительно мы рассмотрим шаблон внутренняя изменчивость (interior mutability), где неизменяемый тип предоставляет API для изменения своего внутреннего значения. Мы также обсудим ссылочные зацикленности (reference cycles): как они могут приводить к утечке памяти и как это предотвратить.

Приступим!

Умный указатель — идиома косвенного обращения к памяти, которая широко используется при программировании на языках высокого уровня: C++, Rust и так далее. Как п

Пользователи также искали:



c++ использование умных указателей,

qt умные указатели,

ravesli умный указатель,

шпаргалка по умным указателям,

умные указатели c++17,

умные указатели java,

unique_ptr передача в функцию,

unique_ptr vs shared_ptr,

указатели,

умные,

умный,

Умный,

умных,

qt умные указатели,

шпаргалка по умным указателям,

c использование умных указателей,

умные указатели java,

Умный указатель,

java,

указателей,

умные указатели c,

указатель,

передача,

функцию,

шпаргалка,

умным,

указателям,

использование,

sharedptr,

uniqueptr,

ravesli,

uniqueptr vs sharedptr,

uniqueptr передача в функцию,

ravesli умный указатель,

умные указатели c17,

c17,

умный указатель,

типы данных. умный указатель,

blog-in binary: 2011

У соседей прошли выборы в Думу.

Власть, не моргнув глазом, пририсовала себе где-то в полтора раза больше голосов, чем они получили на самом деле. Честный результат, судя по статистическим выкладкам, где-то порядка 35% — это все, что жулики и воры смогли выжать, используя админ ресурс и имея абсолютную монополию в области классических СМИ, вроде телевидения.

Цинизм, с которым были нарисованы итоговые 50% очень впечатляет — цифры из протоколов были тупо проигнорированы и на сайте ЦИК, не сильно парясь, просто показали «нужный результат»; я видел в Сети неоспоримые свидетельства десятков подобных случаев, причем некоторые из них рассказаны людьми, которых я знаю не первый год. О чем тут вообще говорить, если на ТВ показывают ведущих, на фоне явки в 120%?
Каганов вообще рассказал анекдотическую историю, когда человек проголосовал за «Яблоко», полез на сайт ЦИК, а там по его участку за «Яблоко» нет вообще ни одного голоса! Блин, это было бы очень смешно, если б не было так грустно.

Мораль?

Пытаться законными способами, типа через суды, разбираться со всеми случаями нарушений — дело совершенно неблагодарное. Страна настолько погрязла в коррупции и беспределе, а сама операция «выборы» рулилась с таким цинизмом и масштабом на столь высоком уровне, что идти в суды и пытаться там что-то доказывать, это все равно, что биться головой о бетонную стену. Ну или пытаться отлить при встречном буране.

Царь-батюшка Путин ложил на вашу демократию с широким пробором. И по доброй воле он и его кодла сильно вряд ли уйдет. В данный момент верховная власть в России обеспечивает права собственности на бизнесы такого масштаба, что Владимиру Владимировичу просто не дадут уйти из Кремля — такими деньгами не шутят, и право их владения нельзя ставить под угрозу.
В общем, это либо будет какая-то очередная перетрубация (а-ля операции «Медвед») с формальной передачей власти нужному человеку, которую власть вынуждена будет сделать, если недовольство народных масс достигнет критической, взрывоопасной точки… Либо кровь. Много крови. Для новой России — нормальный сценарий, они его уже пару раз проходили, по другому они просто не умеют.

Сегодня для свержения не демократической власти путем революции народ категорически не готов. Америка мало занесла. Проблема в том, что вся политическая движуха в стране идет в ключе классической «навальщины» — на воле протестов и возмущений против беспредела со стороны нынешней власти. Это вообще классическая черта менталитета (по себе сужу) — мы не за кого-то, мы скорее против! Нам не хвалить нравится, нам нравится гадить и критиковать. Не созидать, а крушить да ровнять с землею… Так вот, агрессия против нынешних правителей это здорово, но для того, чтобы что-то изменить, нужно созидательное направление, вокруг которого народ сплотится и самоорганизуется… Лозунг «голосуй против ПЖиВ! совершенно не важно, кто пройдет в Думу, главное, что именно этих гадов там будет меньше» есть тупиковый путь, ведущий в никуда.
Кстати, совершенно такая же беда и в Белоруссии — понятно, что бацька плохой, ну а кто хороший?

В России нет внятной, хорошо организованной оппозиции. И задумайтесь, может быть ее нет просто потому, что на нее нет реального спроса со стороны общества. С нефтью все в порядке, цена хорошая, объемы экспорта греют душу. Народ сытый да обутый, благосостояние из года в год растет. На что жаловаться?… Ну да, власть зажралась, прибрала к рукам весь крупный бизнес, национальное достояние растаскали по личным карманам. Да, воруют. Да, коррупция. Но лично тебе, %username%, разве лично тебе так уж и плохо живется? Зачем тебе нестабильность и смута, если ты сейчас, в принципе, живешь не плохо? Лучше синица в руках, да хата с краю!…

***

Мне очень сильно не нравится то, что происходит в России. 

Я не такой наивный, чтобы верить в демократию, просто я согласен с Черчиллем — ничего лучшего пока не придумали. 

То, какая Путин мразь и как быстро он «наведет порядок» я понял буквально в первый же год его правления. Чувак полностью задавил свободную прессу, а это верный и совершенно однозначный знак. 

Мне очень сильно не нравится то, что происходит в России. Потому что очень похоже, что донецкие пытаются ввести режим по образу и подобию в моей стране, а мне бы этого сильно не хотелось. 

Сегодня я вообще, грешным делом, думаю о том, что в президенты надо было выбирать Ющенко на второй срок. Тигипко совершенно внезапно оказался тем еще Иудой и пидарасом, а больше там и выбрать было не из кого. Ну а пасечнику можно было бы простить его невинные игры в вышиванки да любовь к Мазепе. Главное, что этот человек всегда с уважением относился к законам этой страны и никогда не давил на прессу. Ну а легкая форма украинского национализма головного мозга — детский лепет на фоне того, что следующие выборы в моей стране, увы, могут пройти по российскому сценарию. 

секреты бесплатного 3D-редактора Blender / Программное обеспечение

Трёхмерный редактор Blender имеет массу достоинств, и мы уже рассказывали читателям 3DNews об этой замечательной программе (см. материал «Blender 2.45: бесплатный 3D-редактор»). Со времени написания того обзора программа сильно изменилась — у нее появилось множество полезных функций, она стала на порядок мощнее, удобнее, но при этом по-прежнему остается бесплатной. Сегодня мы поговорим не столько о её возможностях (для перечисления всех опций и настроек приложения пришлось бы написать не статью, а увесистый справочный том), сколько о трудностях, с которыми придётся столкнуться тому, кто в первый раз запустит этот 3D-редактор.

На данный момент Blender не может похвастаться длинным списком известных проектов, где бы он использовался. Из более или менее стоящих работ, выполненных с помощью этого 3D-редактора, на ум приходит разве что «Человек-паук — 2» да полнометражный анимационный фильм «Брэндан и секрет Келлов». Ну а лучше всего раскрывает возможности программы проект Llama Drama — это две короткометражных анимации про непутёвую Ламу, сделанные командой профессионалов Blender.

Отсутствие «портфолио» программы можно объяснить лишь тем, что профессионалы в крупных компаниях очень осторожно относятся к бесплатному продукту, который распространяется «как есть». Для солидных анимационных студий очень важно, чтобы продукт не только имел мощный арсенал средств, но еще и развивался, имел хорошую поддержку. В случае же с Blender все построено на сплошном энтузиазме. К тому же, именитые студии сильно привязаны к коммерческому программному обеспечению, отказаться от которого невозможно по целому ряду причин — от проблем, связанных с совместимостью с другим ПО, до очевидного нежелания отказываться от разнообразных заготовок в привычном инструментарии и многолетнего опыта работы с профессиональным дорогим приложением.

Тем не менее с каждой новой версией Blender обретает всё большую популярность среди профессионалов. На данный момент его уже взяли на вооружение десятки анимационных студий, которые успешно используют инструментарий программы для производства мультимедийных презентаций, рекламных роликов и заставок на ТВ. Потенциал программы настолько велик, можно с уверенностью утверждать: появление более серьёзных проектов — это почти наверняка вопрос времени. Так, например, относительно недавно создателем «сердитых птичек» Rovio Stars совместно с английской студией Midoki была выпущена многопользовательская онлайн-стратегия Plunder Pirates. Для производства этой красочной и запоминающейся игры был использован Blender.

Растущая популярность 3D-редактора закономерна, ведь о достоинствах Blender можно говорить очень долго. Эта программа очень мощная, но при этом рационально использует системные ресурсы. Ранние дистрибутивы редактора «весили» всего несколько мегабайт, и уже тогда Blender мог использоваться как полноценный профессиональный инструмент для 3D-моделирования. Сейчас размер установочного файла стал больше, но, по сравнению с дистрибутивами других пакетов для 3D-моделирования и анимации, он все так же имеет намного меньший объем, а по функциональности при этом не уступает именитым программам. Сомневаетесь? Тогда посмотрите следующее видео — все сделано в Blender.

Трёхмерный редактор — программа интересная, но сложная. Если вас действительно увлёк мир 3D, нужно запастись терпением, в особенности когда речь идёт о бесплатном редакторе Blender. Его очень сложно осваивать методом «научного тыка», и это является для многих любителей 3D непреодолимой проблемой. Так, например, в программе отсутствует полноценное главное меню в том виде, к которому все привыкли. Многие средства и команды приложения запрятаны где-то глубоко в интерфейсе или вообще могут быть вызваны только клавиатурными сочетаниями. Для изучения Blender аниматору и дизайнеру определенно потребуется время, чтобы привыкнуть и освоиться в новой среде.

Парадоксально, но именно такая архитектура приложения, сделанная «под себя», и подкупает. Первые навыки работы с Blender приобретаются быстро, и уже через несколько дней интенсивного обучения приходит понимание того, что главная стратегия этой программы заключается в том, чтобы при минимальном количестве действий получить максимальный результат. Вот почему интерфейс Blender лишен необязательных значков, кнопок и прочих элементов.

Если вы решите изучить Blender, вы столкнетесь с массой вопросов, даже если до этого уже занимались созданием 3D. В Blender многое сделано не так, как к этому привыкли пользователи Maya, 3ds max и других коммерческих приложений. К счастью, к Blender прилагается неплохая документация (есть даже вариант перевода на русский язык, правда, не совсем корректный). А еще, по мере того как вы будете знакомиться с командами Blender, на экране то и дело будут появляться всплывающие подсказки с фрагментами официальной документации. Но и этого, конечно, будет мало. Поэтому в данном материале мы попробуем помочь новичкам в вопросе освоения Blender, сделав акцент на некоторых важных особенностях этого трехмерного редактора.

⇡#Интерфейс

Уникальность трёхмерного редактора заключается в том, что Blender сочетает в себе полный набор инструментов для производства анимации. Теоретически можно создать короткометражную анимацию от начала и до конца, используя исключительно средства данной программы. Функции Blender поражают своим разнообразием. Тут есть и модуль для анимации, и средство видеомонтажа, и 2D-рисования, трекинга, и инструменты трёхмерной лепки, и многое другое. Подозреваем, что именно эта «гремучая смесь» самых разнообразных средств для создания трехмерной графики и визуальных эффектов побудила разработчиков дать название программе Blender (в переводе с английского — «смеситель», «мешалка»). И всё это разнообразие инструментов не могло не сказаться на интерфейсе программы — внешний вид трёхмерного редактора может изменяться в зависимости от поставленной задачи.

При работе с Blender придётся выучить длинный список сочетаний клавиш. Без знания горячих клавиш работа в программе попросту невозможна, поэтому обращайте на них внимание по ходу этой статьи. Практически любой функции программы соответствует своя комбинация. Кроме того, горячие клавиши в программе могут менять своё назначение в зависимости от выбранного инструмента программы. Например, если вы работаете в режиме управления объектом Object Mode, клавиша G позволяет быстро перемещать объект в окне проекции. Но если вы включите режим трёхмерного скульптинга, та же клавиша будет вызывать определённый профиль кисти.

Трёхмерные редакторы часто имеют схожий интерфейс — окна проекций, панель с настройками выбираемых инструментов и т.д. Все это вы найдете и в интерфейсе Blender, однако «интуитивно понятным» его назвать нельзя. Он имеет много особенностей, поэтому даже тот, кто имеет хороший опыт создания трехмерной графики в других программах, не сможет сразу приступить к работе. Нужно потратить не один час, чтобы изучить основные компоненты редактора, расположение инструментов, а также некоторые команды для управления интерфейсом.

Приступая к новому проекту, трёхмерщики привыкли все начинать с нуля — наполнять сцену объектами, подбирать их параметры и пр. В Blender пустая сцена уже содержит ряд объектов: куб, источник света и камеру. Интерфейс программы не перегружен лишней информацией, поэтому вы не найдете кнопок для навигации в окне проекции. Управление видом осуществляется средней кнопкой мыши (простое нажатие средней кнопки — вращение сцены, нажатие с одновременным удерживанием клавиши Shift — смещение). Чтобы отдалить или приблизить вид, используйте скроллинг.

Владельцы ноутбуков, которые работают с тачпадом, могут столкнуться с проблемой при управлении видом в окне проекции. На большинстве мобильных ПК тачпады не снабжены средней кнопкой, поэтому некоторые команды в Blender выполнить невозможно. Иногда драйвер к тачпаду предоставляет возможность программной эмуляции нажатия средней кнопки мыши, однако эта опция не всегда работает должным образом на ноутбуке. К счастью, в Blender предусмотрено решение данной проблемы. Откройте окно с настройками программы, выбрав в меню File > Preferences, перейдите на вкладку Input и установите флажок напротив опции Emulate 3 Button Mouse.

После этого в Blender включится режим эмуляции средней кнопки мыши с помощью опциональных клавиш. Например, чтобы выполнить поворот вида в окне проекции, нужно нажать клавишу Alt и левую кнопку мыши одновременно, а чтобы сдвинуть вид в окне проекции, следует нажать Alt+Shift и левую кнопку мыши. Также в настройках можно включить опцию эмуляции цифровых клавиш дополнительной клавиатуры.

Если у вас уже есть некоторый опыт работы с трёхмерными редакторами 3ds max или Maya, вы можете активировать нужный профиль в настройках Blender, что позволит использовать для многих команд привычные клавиатурные комбинации.

При работе с трёхмерной графикой очень важно, чтобы пользователь мог настраивать программу «под себя». Интерфейс Blender очень гибок, его можно настраивать так, как это вам удобно. Элементами интерфейса редактора можно всячески управлять, например можно изменять размеры окон и панелей.

Рабочее пространство Blender можно разделить на условные зоны. Зонами можно считать редактор 3D-вида (3D View Editor), который включает в себя окна проекций, редактор настроек (Properties Editor), а также две панели — панель настроек и панель инструментов. Панель настроек по умолчанию скрыта. Чтобы ее увидеть, нажмите на плюсик в окне с видом сцены или воспользуйтесь клавишей N.

Панель инструментов также можно быстро скрыть или отобразить, воспользовавшись клавишей T.

Редактор параметров (редактор настроек)

Панель инструментов

Размеры панелей с инструментами в Blender можно изменять, можно даже полностью «задвинуть», убрав с экрана. Любую скрытую панель можно открыть с помощью значка в виде плюса, который появляется на месте спрятанного элемента интерфейса.

Интерфейс программы можно очень просто и удобно «дробить», разделяя его на новые окна и настраивая их содержимое. Вы можете, скажем, разделить окно проекции на два окна, в одном из которых оставить вид на сцену, а в другом включить режим отображения редактора кривых (Graph Editor). В правом верхнем углу любого окна программы можно увидеть крохотный треугольник. Чтобы разделить текущее окно на два, просто потяните этот треугольник.

Интерфейс Blender до и после операции «дробления» окон Split

Как правило, начинающие пользователи быстро находят способ «дробления» окон, создают их в большом количестве, а затем теряются в догадках, как убрать ненужные элементы интерфейса. Это еще одно свидетельство того, что в Blender многие операции реализованы неявно, и поиск нужных команд нередко превращается в утомительный квест. Чтобы скрыть какое-нибудь из окон интерфейса, его можно задвинуть в сторону, а чтобы полностью убрать окно, его следует объединить с соседним. Для объединения нужно поднести курсор к границе между окнами, а затем щелкнуть правой кнопкой мыши, в контекстном меню выбрать Join Area и навести указатель на то окно, которое требуется убрать.

Есть еще один способ дробления интерфейса редактора: нужно поднести курсор к границе между окнами, в контекстном меню выбрать Split Area и с помощью разделительной линии определить положение границы раздела новых окон.

По умолчанию в Blender отображается только один вид проекции — перспектива. Но для полноценной работы с 3D вам понадобится и классический обзор объектов — сверху, сбоку, спереди и т.д. Чтобы переключиться в привычный для CAD-приложений четырехоконный интерфейс воспользуйтесь сочетанием клавиш Alt+Ctrl+Q.

Еще одна удобная особенность интерфейса Blender — масштаб любого окна программы можно менять. Не размер окна, а именно масштаб, то есть делать элементы интерфейса более крупными. Для этого используйте клавиши «плюс» и «минус» на дополнительном цифровом блоке клавиатуры. Эффект масштабирования окон редактора чем-то напоминает изменение масштаба в браузере — читать надписи становится проще, вводить значения — удобнее. Данная опция будет особенно актуальна, если вы работаете на мониторе с очень высоким разрешением.

Одна из отличительных особенностей Blender — трехмерный курсор (правильнее его было бы назвать трехмерным маркером). Этот объект постоянно присутствует в сцене и является вспомогательным элементом для указания точных координат. Он помещается в той точке виртуального пространства, куда вы щелкнули мышью. Для трёхмерного курсора используется принцип привязки, поэтому его очень просто поместить, например, на поверхность трёхмерной модели. Если вы «потерялись» в виртуальном пространстве и не видите трёхмерный курсор, нажмите Shift+C. При этом трёхмерный курсор будет установлен в центр сцены, а вид будет изменен так, чтобы вы смогли его наблюдать.

Трёхмерный курсор Blender

Интересно, что при работе с разными 3D-редакторами пользователи сталкиваются с одними и теми же проблемами интерфейса. Например, в сообществах начинающих любителей 3D нередко можно увидеть вопрос «куда пропали стрелки?». Дело в том, что в большинстве трехмерных редакторов для операций трансформации (вращение, перемещение и масштабирование) принято использовать вспомогательный манипулятор — указатель с направлениями. На каком-то этапе изучения программы неопытный пользователь нажимает «не ту кнопку», и этот манипулятор исчезает с экрана. Выполнять поворот и перемещение объектов вслепую довольно неудобно, и пользователь тратит на поиски решения этой проблемы свои нервы и драгоценное время.

Blender тоже имеет подобный манипулятор, который может внезапно исчезнуть. Если он пропал с экрана, скорее всего, вы случайно нажали сочетание клавиш Ctrl»+»Space. Нажмите эту комбинацию повторно, и манипулятор снова отобразится на экране. Для включения и отключения манипулятора также используется соответствующая кнопка под окном проекции. Вращать, перемещать и масштабировать объекты можно также с помощью быстрых команд: G — позволяет быстро перемещать выделенный объект, R — вращать, S — масштабировать. Знание этих команд крайне необходимо, и особенно пригодится, когда вы будете заниматься моделированием.

Кнопки для включения операций трансформации и переключения в режимы перемещения, вращения и масштабирования.

В программе имеется очень удобная система поиска. С ее помощью вы всегда можете отыскать нужную вам команду. Откройте меню поиска с помощью клавиши «Пробел» и начните вводить название нужной опции. Blender постарается помочь подсказками. Иногда это здорово ускоряет работу. Например, если вы работаете над динамикой компьютерной игры, не нужно для каждого отдельного объекта указывать физические свойства. Достаточно набрать game, и в списке появится команда Copy Game Physics Properies to Selection, которая позволит быстро передать физические свойства выделенным объектам сцены.

⇡#Моделирование

В трёхмерной графике существует много приёмов моделирования. Создавать трехмерные поверхности можно, например, при помощи инструментов полигонального моделирования, когда поверхность модели состоит из многоугольников, можно заниматься трёхмерным скульптингом, используя виртуальные кисти (как в программе ZBrush), можно использовать моделирование при помощи сплайнов (трёхмерных кривых) и так далее. В Blender реализованы все наиболее часто встречаемые способы моделирования.

Самый простой и популярный метод — полигональное моделирование, при котором трёхмерная форма создается путём редактирования подобъектов каркаса модели — вершин, ребер и поверхностей (полигонов). Для того чтобы начать работу с этими подобъектами, необходимо включить режим редактирования Edit mode. По умолчанию в редакторе задействован режим работы с объектами Object mode, в котором можно управлять положением и ориентацией объектов трёхмерной сцены. Чтобы переключиться в режим редактирования объекта, следует выбрать нужную команду из списка режимов работы.

Список режимов работы Blender

При создании сложной топологии трехмерной модели, например в процессе моделирования трехмерного персонажа, часто приходится использовать так называемое мягкое выделение (soft selection). Суть его сводится к тому, что когда вы выделяете один или несколько подобъектов каркаса, например пару вершин, их перемещение (или другая операция трансформации — вращение, масштабирование) в окне проекции окажет влияние на прилегающие подобъекты (вершины). Причем степень воздействия на прилегающие вершины зависит от расстояния между редактируемым подобъектом и прилегающими вершинами — чем дальше подобъект от редактируемой области, тем слабее его трансформация.

Понятие soft selection является универсальным. Эту команду можно найти практически в каждом 3D-редакторе — в Maya, 3ds max, Cinema 4D и пр. Но в Blender эта команда отсутствует, и поиск по документации вам не поможет. Дело в том, что разработчики её назвали иначе — proportional editing. Для активирования режима мягкого выделения нужно нажать клавишу O, а чтобы изменить диаметр области воздействия, используйте в процессе редактирования колесо скроллинга мыши. Управлять площадью воздействия на прилегающие вершины можно также с помощью клавиш PgUp и PgDn (эти клавиши следует удерживать при выполнении операций трансформации). Свойства режима мягкого выделения также доступны на панели инструментов слева от окна проекции.

Создавать новые поверхности можно вручную. Чтобы создать новый полигон, необходимо выбрать вершины, через которые он будет проходить, после чего нажать клавишу F. А простейший способ создать вершину — щелкнуть левой кнопкой мыши при нажатой клавише Ctrl.

Объединение подобъектов — одна из самых частых операций в программе, особенно важная для редактирования каркаса модели. Чтобы объединить два подобъекта, скажем две вершины, нужно выделить их, удерживая клавишу Shift, а затем нажать сочетание Alt+M. Программа отобразит контекстное меню с настройками объединения подобъектов.

На этапе моделирования может возникнуть необходимость преобразования объекта в редактируемую оболочку (например, если вы сделаете объемный текст, а затем решите его доработать стандартными средствами редактирования каркаса модели). Для быстрого преобразования сплайновой формы в редактируемый каркас можно использовать сочетание клавиш Alt+C. На экране появится меню, где можно выбрать команду преобразования.

⇡#Режим трёхмерной лепки

В отличие от прочих приёмов моделирования, цифровой скульптинг ориентирован на интуитивно-творческий подход к созданию трёхмерных форм. Без такого инструмента теперь не обходится ни один крупный CG-проект. Органические формы очень трудно программировать и делать «под линейку», для хороших художников гораздо легче творить руками, пусть и в виртуальном мире. Самая популярная программа для скульптинга — ZBrush, с помощью которой были созданы, например, чудища из «Пиратов Карибского моря», персонажи фильма «Аватар» и пр. Эта программа всем хороша, но цена на неё составляет почти восемьсот долларов. Инструмент для цифрового скульптинга в Blender во многих случаях может заменить ZBrush, поскольку содержит базовые опции, предлагаемые в продукте компании Pixologic.

Чтобы начать творить в Blender с помощью виртуальных кистей, нужно задействовать режим Sculpt Mode. Вы можете использовать кисти с разными профилями, создавать собственные варианты деформаций, назначать маски. В программе есть и возможность симметричной лепки. При создании модели используется алгоритм динамической топологии, который позволяет уплотнять каркас модели, увеличивая детализацию трёхмерной поверхности в местах деформации. Blender поддерживает работу с графическими планшетами, и, если в настройках кисти активировать соответствующую опцию, модуль цифровой лепки будет учитывать степень нажатия цифрового пера.

При переходе в режим трёхмерной лепки можно использовать небольшую библиотеку с профилями кистей (доступно два десятка разных профилей). Blender дает возможность быстро выбирать нужный профиль кисти с помощью горячих клавиш. Запоминаются они легко: клавиша S вызывает профиль кисти Smooth для сглаживания неровных вершин, клавиша P активирует профиль Pinch (щипок), который, воздействуя на вершины, стягивает их к центру области редактирования, клавиша G вызывает профиль кисти Grab и т.д.

Конечно, по функциональности ZBrush намного мощнее, движок трёхмерной лепки компании Pixologic более продуман и разнообразен. Но, с другой стороны, для ZBrush очень желательна интеграция с профессиональным 3D-редактором, в то время как Blender сам по себе является полноценным редактором.

В Blender есть огромный арсенал инструментов для моделирования, настройки персонажной оснастки и еще много других средств для создания 3D, которых в ZBrush попросту нет. Про финансовый аргумент также не стоит забывать — нужно хорошо подумать, имеет ли смысл платить деньги за функции, которыми не придётся пользоваться.

⇡#Модификаторы

Инструменты трёхмерных редакторов часто повторяют друг друга. Действительно, придумать что-то новое очень сложно, поэтому принципы построения 3D-модели во всех программах очень схожи. А в Blender есть даже целый класс инструментов, который повторяет аналогичные средства для трёхмерного моделирования и анимации в 3ds max. Мы имеем в виду модификаторы. Да, Blender, как и популярный коммерческий пакет от Autodesk, также содержит группу модификаторов самого разного предназначения. На первый взгляд, если сравнить список модификаторов Blender с аналогичным в 3ds max, можно увидеть, что инструментарий бесплатного редактора выглядит куда более скромно.

Но тут стоит вспомнить об одной немаловажной детали — бесплатный инструмент создавался не для продажи, а для работы. В 3ds max есть некоторые модификаторы, которые на практике используются крайне редко, а есть и такие, которые практически дублируют назначение друг друга, как, например, Meshsmooth и Turbosmooth. Таким образом, если отмести в сторону «шелуху», пропасть между 3ds max и Blender становится не такой и большой. Уже через несколько минут после экспериментов с модификаторами Blender можно установить прямую аналогию между названиями: модификатор Solidify — это тот же модификатор Shell из 3ds max, блендеровский модификатор Smooth во многом схож с модификатором Relax и т. д.

⇡#Освещение

Источники освещения всегда играют большую роль. Их настройка тесно связана с параметрами движка визуализации. В зависимости от выбранного типа движка визуализации набор параметров созданного источника света может быть несколько иным.

Настройки источника Spot для Blender Render

Настройки источника Spot для Cycles Render

Самые простые из источников света в Blender — точечный источник Point и направленный осветитель Spot. Помимо них есть также Sun, Area и Hemi. Изменять тип виртуального источника света можно на лету, используя для этого соответствующую кнопку в параметрах данного объекта.

Если включить режим интерактивного рендеринга движком Cycles (выбрать в списке Cycles Render и нажать Shif+Z), можно увидеть, что при отсутствии источников освещения сцена все равно видна — она подсвечивается серым цветом окружения, который указан в настройках на вкладке World.

Несмотря на то, что в настройках объекта Sun имеется параметр, определяющий величину источника света, как таковой площади осветительной поверхности в окне проекции вы не увидите. Данный источник света нужно воспринимать как бесконечную стену света, упрощенную модель такого очень крупного осветителя как Солнце. По этой причине перемещение источника света Sun в окне проекции не оказывает влияния на общую картину освещенности сцены — где бы он ни находился в сцене, интенсивность светового потока и тени остаются неизменными. Чтобы изменить освещенность, можно повернуть этот источник света на какой-нибудь угол. Следует учитывать, что при увеличении размеров источника Sun световая энергия распределяется на большую площадь, и яркость света на отдельных объектах сцены при этом становится меньше.

Источник света Hemi не поддерживается движком визуализации Cycles и интерпретируется им как Sun. Этот объект представляет собой полусферу, поверхность которой излучает свет. Данный тип источника может применяться для имитации небосвода.

⇡#Материалы и текстурирование

На этапе настройки материалов в Blender понимаешь, насколько удобен интерфейс этой программы и насколько правильно сделали разработчики, взяв за основу принцип «инструменты программы не должны перекрывать друг друга». Создав небольшое отдельное окно с интерактивным рендером (включается сочетанием клавиш Shift+Z или выбором варианта отображения объектов в окне проекции Rendered) и расположив его, например, под редактором настроек (Properties Editor), можно вместо окон проекций открыть редактор узлов и «колдовать» в нем, подбирая необходимые параметры материалов.

В Blender редактора материалов как такового нет, зато имеется более гибкое и наглядное средство — редактор узлов. Выбирается он в том же меню, где находятся команды для перехода в режим редактирования, режим работы с Timeline и т.д.

Для движка визуализации Cycles Render материалы являются сочетанием трех основных настроек: Surface (рисунок поверхности), Volume (фактура объема) и Displacement (рельеф материала). К этим настройкам можно привязывать шейдеры, текстуры, а также всевозможные комбинации доступных узлов. Комбинации узлов в конечном итоге и определяют внешний вид поверхности модели, а также задают характер заполнения объема каркаса модели и описывают визуальный эффект смещения поверхности сетки.

Чтобы создать новый материал и перейти к его настройкам, следует выделить объект в окне проекции, перейти на вкладку Material редактора параметров, а затем нажать на кнопку Add new material. На панели отобразятся главные характеристики упомянутых выше параметров — настройки объема Volume, параметра смещения Displace и настройки поверхности Surface.

Базовые параметры можно указать в панели параметров Blender, а для более тонкой настройки необходимо вызвать редактор узлов Node Editor. Выбрав режим отображения на экране редактора узлов, установите флажок Use nodes, чтобы увидеть содержимое диаграммы. После того как вы создадите первый материал, в редакторе узлов появятся первые блоки узловых диаграмм.

Для управления свойствами материалов начинающим пользователям Blender придется основательно изучить свойства узлов, которые можно использовать в проекте. Работа с материалами в Blender напоминает игру с конструктором. Конечный результат может выглядеть как весьма замысловатая диаграмма связей.

Сами узлы (или, попросту говоря, наборы свойств материала) можно увидеть слева от окна редактора узлов — на панели инструментов. Для ускорения работы можно использовать сочетание клавиш Shift+A — эта команда открывает контекстное меню для быстрого доступа к узлам.

При наличии связей в диаграмме, одни узлы оказывают влияние на другие, и так происходит формирование свойств материала. Например, связь между сокетом Color («цвет») в узле Diffuse BSDF и сокетом Color в узле процедурной текстуры Wave Texture («волновая текстура») приведет к тому, что объект покроет волнообразный рисунок. А если соединить сокет Fac узла Wave Texture со слотом Displacement узла Material Output, поверхность создаваемого материала покроют волнообразные вмятины, характер которых будет определяться рисунком все той же процедурной текстуры Wave Texture. Таким образом, смешивая компоненты в редакторе узлов, можно получить материал с любыми свойствами — матовый или зеркальный, со свечением, с эффектом подповерхностного рассеивания, как в воске, с рельефом, покрытым узором, и т.д.

Связь между узлами устанавливается просто — достаточно захватить курсором мыши один из так называемых сокетов (круглые цветные точки на правой или левой стороне узлового блока) и потянуть его на аналогичный сокет другого узла. Чтобы разрушить связь между узлами, нужно захватить один из узлов и, оттянув линию связи в сторону, отпустить левую кнопку мыши.

Названия шейдеров в Blender часто включают в себя приставку в виде нескольких букв, например Glass BSDF или Subsurface Scattering BSSRDF. Эта приставка сообщает о математической составляющей алгоритма визуализации материала. Аббревиатура BSDF расшифровывается как «модель двунаправленной функции распределения рассеивания света». По сути, это алгоритм, который описывает отраженный свет, а также сильно упрощенную схему подповерхностного рассеивания. BSSRDF (Bidirectional Surface Scattering Distribution Function) — это двунаправленная функция распределения поверхностного рассеивания, которая позволяет более корректно визуализировать прохождение света через материал.

При работе с редактором узлов имеет смысл включить одно из стандартных дополнений к Blender под названием Wrangler node. Этот модуль ускорит работу в окне Node Editor. Скажем, чтобы создать связь между каким-нибудь шейдером, например Subsurface Scattering BSSRDF и узлом Subsurface Scattering BSSRDF, достаточно нажать Shift+Ctrl и щелкнуть по заголовку узлового блока Subsurface Scattering BSSRDF.

Текстовые узлы удобно группировать. Например, если создать узел Frame и перетащить в него несколько узлов, образующих свойство какого-то материала, появится цельная группа компонентов, которую можно будет перемещать и использовать в работе.

Для активированного дополнения Wrangler node, о котором упоминалось выше, эта операция выполняется еще проще — с помощью сочетания клавиш Shift+P.

В некоторых случаях возникает необходимость временно отключить те или иные узлы, не прерывая цепочку связей в диаграмме. В этом случае можно просто «замкнуть» узел с помощью клавиши M. В результате работы этой команды входной и выходной сокет узла будет автоматически замкнут, и данный компонент перестанет оказывать влияние на материал. Повторное нажатие на клавишу М уберет «замыкание».

⇡#Визуализация: движки визуализации, работа со слоями, композитинг

Механизм визуализации в Blender универсален, как и подобает профессиональному 3D-редактору. Программа поддерживает как собственный алгоритм просчета финального изображения, так и сторонние движки, обеспечивающие альтернативные методы анализа сцены. Среди наиболее популярных модулей, с которыми совместим Blender, можно выделить Yafaray, LuxRender, Maxwell Render (необходим неофициальный модуль B-Maxwell), V-Ray, OctaneRender. Однако использование этих модулей не является обязательным условием для получения реалистичного изображения (если, конечно, грамотно использовать стандартные средства визуализации).

По умолчанию в Blender есть три движка визуализации: Blender render — быстрый классический алгоритм просчета, Cycles — движок, алгоритм которого основан на методе трассировки света, а также Blender game — интерактивный игровой движок.

Cycles Render оптимизирован для использования в режиме реального времени. При наличии мощной видеокарты он может относительно быстро визуализировать трехмерную сцену с достаточно высоким уровнем реалистичности. Запуск визуализации включается клавишей F12, а чтобы сохранить отрендеренный кадр, нужно нажать F3 и указать формат и расположение файла на диске.

Стандартный движок рендеринга имеет массу настроек. В программе выделен набор слотов, всего восемь штук (в версии Blender 2.75a). Нажимая клавишу J, можно быстро переключаться между вариантами визуализированных изображений, сравнивая результат.

Следующая функция визуализации будет особенно полезна при сравнении разных вариантов изображений. В опциях визуализации (вкладка Render редактора параметров, свиток Metadata) можно включать режим отображения так называемого штампа — вспомогательной надписи, которая помещается поверх отрендеренного изображения и отображает сведения о текущем проекте. Штамп может показывать имя сцены, время, затраченное на обработку изображения, дату создания изображения и место расположения файла на диске, номер кадра в анимации и пр. В этом штампе можно также оставлять свои собственные текстовые комментарии.

Нужно сказать, что от выбора движка визуализации зависит не только качество финального изображения, но и сам процесс работы над 3D. Например, когда вы занимаетесь настройкой текстур, отображение UV-карты в окне проекции включается по-разному. Для классического движка Blender Render это происходит автоматически, а для Cycles Render необходимо настраивать отображение через редактор узлов.

Рендеринг в Blender вынуждает постоянно искать «золотую середину» между продолжительностью обработки сцены и приемлемым качеством финальной картинки. Поэтому вполне очевидно, что в арсенале трёхмерного редактора присутствует целый ряд инструментов, предназначенных для композитинга. Если у вас недостаточно опыта работы с 3D и термин «композитинг» вам не говорит ни о чём, мы внесём ясность и объясним, что это такое.

Не секрет, что визуализация — это самая утомительная процедура при работе над проектом. Чем лучше качество, тем дольше компьютер обрабатывает изображение. Подбор нужных параметров визуализации занимает невероятно много времени, ведь после каждой новой попытки нащупать «золотую середину» между скоростью просчета и качеством картинки приходится ждать окончания рендеринга. Порой подбор настроек визуализации столь утомителен, что рациональнее пойти другим путём — выполнить визуализацию всего один раз, сделав поэлементный рендеринг. Результатом будет набор отдельных изображений, каждое из которых содержит рисунок своего параметра — изображение с бликами, рисунок теней, изображение с цветом диффузного рассеивания и т. д. Объединив все эти изображения в виде слоёв, мы получаем результирующее изображение, которое очень просто отредактировать на любом уровне — исправить цвет, изменить отражение и др. Все это делается мгновенно средствами постобработки изображения, без необходимости повторной длительной визуализации. Если вы виртуозно работаете со слоями в Photoshop, то легко представите себе преимущества композитинга перед визуализацией всей сцены сразу, в один проход.

Blender позволяет разбивать сцену на отдельные слои, группы слоев, а также дает возможность выполнять поэлементный рендеринг. Кроме этого одним из удобных средств композитинга является все тот же редактор узлов, который помогает сводить отдельные слои изображения или фильма, настраивать монтаж через альфа-канал и т. д. Управление слоями проекта выполняется с помощью значка в виде набора ячеек. Точками в этих ячейках показано наличие объектов в слоях. По умолчанию в новом проекте сразу присутствует первый слой, который содержит все элементы трёхмерной сцены. Чтобы перенести объект на новый слой, нужно выделить объект в сцене, нажать клавишу M и выбрать ячейку слоя, на который следует поместить новый объект. Чтобы работать с несколькими слоями одновременно, их необходимо выделить, удерживая при этом клавишу Shift. Для более удобного управления слоями и группами слоёв перейдите на вкладку Layers панели свойств. Там же вы найдете простой менеджер слоёв, набор ячеек для визуального представления слоев рендеринга (повторяет инструмент под окнами проекций), а также ряд настроек для задействования поэлементного рендеринга.

⇡#Анимация

Анимация — это очень широкое понятие. Существует классическая компьютерная анимация — анимация по ключевым кадрам, отдельный раздел трёхмерной графики — персонажная анимация, еще отдельная группа средств потребуется для просчёта и моделирования физических процессов. В Blender представлено такое разнообразие инструментов, что их хватит для решения любой задачи, связанной с анимацией.

Прежде всего, стоит упомянуть классический прием создания анимации — по ключевым кадрам. Чтобы анимировать сцену таким способом, выберите положение объекта в сцене, установите положение бегунка на временной шкале Timeline и нажмите клавишу I. Далее в контекстном меню выберите анимируемый параметр и укажите команду для создания ключа анимации.

Еще более простой способ анимировать объекты сцены — в режиме автоматического создания ключевых кадров. Этот режим активируется нажатием красной кнопки, которая расположена возле кнопок для управления воспроизведением анимации. Более тонкая настройка анимации выполняется в окне Graph Editor. В редакторе графов вы найдете графики зависимостей анимируемых параметров, на которых маркерами будут отмечены ключевые значения. Выделив маркер, в настройках можно изменить тип излома кривой, оказав влияние на характер протекания анимации в ключевой точке.

Некоторые инструменты Blender не сразу бросаются в глаза, даже если вы уже работаете с этой программой в течение какого-то времени. Например, средство для управления связанными параметрами — driver. Об этой возможности Blender как-то не очень часто вспоминают в уроках и документации, и, между прочим, зря. Ведь drivers — это одна из изюминок бесплатного 3D-редактора. С помощью этой функции можно, например, связать вращение колес автомобиля с его положением, чтобы при перемещении машины не нужно было каждый раз анимировать движение колес. Или, например, можно синхронизировать движение отдельных деталей сложного механизма — шестерёнок, пружин и пр. Драйверы также используются для упрощенного управления оснасткой персонажа. Настройка драйверов выполняется с помощью редактора графов, переключенного в режим Drivers.

Любопытно, что числовые параметры объектов, которые доступны в интерфейсе Blender, можно заменять выражениями и функциями. Например, если в поле параметра Seed, который обеспечивает случайное распределение шума на визуализированном изображении, вместо числового значения написать #frame, Blender будет в каждом кадре генерировать новую выборку случайных значений, в зависимости от номера кадра.

⇡#Динамика твердых тел

Динамика твердых тел в Blender реализована просто и удобно, движок для просчета физики соударений работает превосходно. Аниматор имеет возможность моделировать взаимодействия между «твердыми» объектами, а также составлять конструкции — например, соединять повторяющиеся звенья цепи. Решение физических задач может также включать такие особенности взаимодействий, как разрушение конструкций (опция Breakable), геометрия поверхности соударения, определение внешних сил и пр. Если у вас есть опыт создания анимации в других приложениях, разобраться с аналогичной функцией в Blender будет делом нескольких минут. В бесплатном редакторе процесс настройки сцены с анимацией взаимодействующих тел логичен и максимально упрощён. Выделить объект, перейти на вкладку Physics, нажать на кнопку Rigid Body и указать тип объекта: подвижный — active или неподвижный — passive. Всё! Простейшая анимация готова. Запускайте воспроизведение в окне проекции и смотрите, что из этого получилось.

Не вызывает нареканий и модуль для симуляции ткани. Деформация ткани создается благодаря модификаторам Cloth и Collision. Первый, то есть Cloth, назначается объектам, которые должны играть роль ткани в сцене. Тут стоит обратить внимание на топологию «тряпичной» модели — реалистичная деформация возможна лишь при достаточной плотности полигональной сетки, поэтому чаще всего имеет смысл еще до симуляции увеличить число вершин модели с помощью модификатора Subdivision. Модификатор Collision назначается объектам, с которыми происходит столкновение ткани. Симуляция поведения ткани запускается сама по себе, при воспроизведении анимации в сцене. Ткань имитируется очень реалистично, артефакты минимальны и легко устраняются увеличением значений параметров Steps и Quality.

⇡#Анимация жидкостных эффектов

Не так давно мы рассказывали читателям 3DNews об очень интересном инструменте компании NextLimit — симуляторе жидкостных эффектов RealFlow (см. материал «Обзор симулятора жидкости RealFlow: невероятные фокусы с водой»). Бесплатный трёхмерный редактор включает в себя модуль, который, как и RealFlow, может моделировать всевозможные текучие эффекты. И, как вы можете увидеть ниже, шоколадные батончики в руках опытного аниматора Blender получаются не хуже, чем в симуляторе компании NextLimit.

Вероятно, на этом месте у любителей 3D возникнет вполне очевидный вопрос: «А какой инструмент лучше»? Сравнивать движок жидкостных эффектов в Blender с алгоритмом RealFlow было бы не совсем корректно и правильно. По точности просчёта, а также по разнообразию инструментов для настройки эффектов Blender, несомненно, уступает специализированному продукту испанских разработчиков. Но это никоим образом не умаляет достоинств модуля для работы с «флюидами» в Blender. При корректной настройке параметров взаимодействия и правильной геометрии взаимодействующих объектов результат выглядит вполне реалистично.

Кроме того, просчет жидкостной анимации происходит очень быстро. При этом процесс «запекания» (так в Blender называется операция по просчету анимации жидкости) щадит ресурсы системы, и компьютер не тормозит. В случае необходимости в настройках анализа сцены можно установить число вычислительных потоков, чтобы еще больше снизить нагрузку.

Инструменты данного модуля находятся на последней вкладке панели параметров — Physics. Моделировать анимацию жидкостей достаточно просто. Предположим, вы задались целью смоделировать простейшую сцену — наполняющийся водой стакан. В физической модели участвуют два объекта — стакан и источник жидкости. Однако для создания подобной анимации в Blender вам понадобятся не два, а три объекта: модель стакана, произвольный объект (например, сфера) и параллелепипед. Произвольный объект служит источником жидкостного потока, стакан представляет собой препятствие, с которым взаимодействует жидкостный поток. Последний же объект, параллелепипед, необходимо отнести к категории Domain — это тип объектов, который определяет область виртуального пространства, где будет происходить анализ физической задачи. Следовательно, размеры параллелепипеда и его расположение должны быть таковы, чтобы в его объеме расположились все объекты симуляции.

Для описания роли каждого из объектов вы выполняете одно и то же действие — выбираете в окне проекции объект, переходите на вкладку Physics и нажимаете на кнопку Fluid. Далее в настройках указываете роль, которую объект будет играть в симуляции: будет ли это источник потока (Inflow), объект, с которым поток должен взаимодействовать (Obstacle), поглотитель водного потока (Outflow) и т. д. (ищите параметр Type в свитке Fluid). Направление потока определяется значением вектора скорости Inflow Velocity. Последний шаг настройки сцены — запекание, то есть просчёт поведения жидкости. Для запуска просчёта нужно выделить объект, в свойствах которого указан тип Domain, а затем нажать на кнопку Bake. В настройках жидкости вы найдете три базовых профиля для создания потоков с характерными текучими свойствами — мёда, масла и воды.

⇡#Работа с частицами: волосы, дым, огонь и прочее

В опытных руках источники частиц превращаются в один из самых мощных инструментов для создания анимационных эффектов. Когда мы говорим о частицах, на ум в первую очередь приходят банальные сюжеты: падающие капли дождя, пролетающий снег, пыль в воздухе, песчинки на пляже и т.д. Однако на самом деле частицы могут использоваться для гораздо более сложных задач, чем моделирование стайки птиц или косяка рыб. В Blender на основе частиц создан ряд анимационных эффектов: огонь, дым, а также… моделирование волос.

Принцип создания дыма и огня практически аналогичен тому, который использовался для имитации жидкостных эффектов. В сцене создаются несколько объектов, среди которых должен быть источник эффекта (огня или дыма) и контейнер Domain, внутри объема которого программа будет выполнять просчёт анимации. Также в сцене может находиться объект, который будет препятствовать распространению эффекта, взаимодействуя с ним.

В отличие от многих 3D-редакторов, в Blender симуляция эффекта отображается в режиме реального времени, что значительно упрощает настройку анимации.

Результат создания огня и дыма вполне реалистичен.

 

Для моделирования волос следует перейти на вкладку Particles и создать новый источник, указав в его настройках тип Hair. Установив флажок напротив опции Hair Dynamics, вы получите доступ к параметрам, которые позволят настроить динамику волос.

Как правило, моделируя волосы, приходится очень точно управлять их положением на модели. Для этой цели на модели выделяется область, затем этой области присваивается какое-то имя и в настройках частиц отмечается, к какой группе выделенных вершин будут привязаны волосы. Чтобы обозначить группу вершин (Vertex Group) на объекте, выделите в режиме редактирования нужные полигоны модели, перейдите на вкладку Data и в свитке Vertex Groups создайте новую группу, дав ей какое-то имя. Перейдите в режим работы с объектом, в настройках источника частиц в свитке Vertex Groups щелкните напротив параметра Density (плотность размещения волос) и выберите из списка имя той группы вершин, которую вы только что создавали. После этого волосы будут распределены только по нужной области.

Моделировать прическу очень удобно с помощью режима Particle Edit. В этом режиме у вас появляется возможность в буквальном смысле «причесать» ваш персонаж. С помощью набора инструментов и виртуальных кистей вы можете укладывать волосы в нужном направлении, подрезать их в определенных местах, наращивать, завивать и т.д. Все инструменты для работы с укладкой волос располагаются на вкладке Tools панели инструментов слева.

Стоит отметить, что для визуализации волос большое значение имеет тип выбранного движка визуализации. Например, классический Blender Render позволит просчитать сцену быстрее, однако этот движок имеет существенный недостаток — для имитации реалистичных прядей необходимо подготавливать материал для волос, оперируя маской прозрачности и подбирая нужным образом освещение. Иными словами, результат получается «поддельный». В последних версиях Blender была добавлена поддержка визуализации с помощью движка Cycles. Это упростило задачу аниматорам, поскольку отпала необходимость имитировать градиентную прозрачность и стало возможным применять обычную процедуру подготовки материала для волос и шерсти. Единственный недостаток Cycles — менее высокая скорость по сравнению с Blender Render. Но, как говорится, красота требует жертв.

 

⇡#Дополнения к Blender

Хотя Blender содержит огромное количество инструментов, совершенству нет предела. Чтобы улучшить программу, можно использовать дополнительные модули. Их не так много, как, скажем, плагинов для 3ds max, однако они есть, и большая часть их бесплатна. Любителей 3D, которые захотят освоить Blender, особенно порадуют бесплатные фотореалистичные визуализаторы Yafaray и LuxRender.

Устанавливаются дополнения к Blender очень просто и удобно — прямо из ZIP-архива. В меню программы следует выбрать File > User Preferences, затем нажать кнопку Install from File и указать расположение архива с дополнением к Blender. После этих действий дополнение появится в списке, и его нужно активировать, установив флажок напротив названия. Как правило, дополнения к Blender от сторонних разработчиков следует искать в разделе Community.

⇡#Заключение

Мало какая бесплатная программа может похвастаться потенциалом, достаточным для того, чтобы соревноваться с коммерческими приложениями, цена на которые составляет сотни и даже тысячи долларов. Но Blender — это приятное исключение из правил. Производительность Blender радует во всех отношениях. Программа мгновенно запускается, легко переключается от инструмента к инструменту, не блокирует работу других приложений. Большинство недостатков трёхмерного редактора — это, скорее, неудобства, связанные с непривычным интерфейсом Blender, а также с необходимостью запоминать большое количество сочетаний горячих клавиш. По большому счёту, это мелочи, ведь Blender — очень и очень мощный инструмент, предлагаемый бесплатно.

Данный редактор — отличный шанс сэкономить огромные деньги на производстве трехмерной графики и на визуальных эффектах. Инструменты Blender работают на порядок стабильнее аналогичных в том же 3ds max, а разнообразие средств для моделирования и создания анимации — выше всяких похвал. Программу нельзя назвать самой простой среди всех 3D-редакторов, однако для её изучения не нужно выкладывать огромные суммы на специализированные курсы и платить за лицензию. Любую подробную информацию о Blender, уроки, советы и документацию вы без труда найдёте в Интернете. К тому же первые «подводные камни» вам будут не страшны, ведь о многих из них мы вам уже рассказали. Ну а если что-то не будет поначалу получаться, стоит вспомнить, что мир трёхмерной графики бесконечен. Азы трёхмерного редактора можно освоить галопом за «25 уроков», но шлифовать свои навыки придётся еще очень долго.

Если Вы заметили ошибку — выделите ее мышью и нажмите CTRL+ENTER.

Откажитесь от указателей в стиле C для интеллектуальных указателей

Подобно моей рекомендации отказаться от встроенных массивов, пора отказаться от базовых необработанных указателей на интеллектуальные указатели C ++. Использование необработанных указателей делает вас уязвимым для множества ошибок:

  • Утечка памяти
  • Освобождение памяти, которую не следует освобождать (например, указатель на статически выделенную переменную)
  • Неправильное освобождение памяти — free () vs align_free (), delete vs delete []
  • Использование памяти, которая еще не была выделена
  • Память мышления все еще выделяется после освобождения, потому что сам указатель не был обновлен до NULL

Большинство этих проблем возникает из-за количества деталей, которые мы должны помнить, чтобы писать код без ошибок.К счастью, C ++ предоставляет три типа интеллектуальных указателей, которые устраняют многие грубые головные боли:

  • std :: unique_ptr
  • std :: shared_ptr
  • std :: weak_ptr

Если вы не знакомы с этими интерфейсами, просмотрите мое введение в интеллектуальные указатели C ++, прежде чем продолжить. Поскольку я уже рассмотрел справочную информацию об использовании этих указателей, я собираюсь сосредоточиться на соответствующих вариантах использования для каждого указателя.

Как правило, я рекомендую использовать std :: unique_ptr в качестве интеллектуального указателя по умолчанию.Если вы обнаружите, что вам нужно обмениваться данными или использовать подсчет ссылок, вам следует использовать std :: shared_ptr . Если вам нужно ссылаться на общие данные, но вы не хотите вносить вклад в счетчик ссылок, используйте std :: weak_ptr .

std :: unique_ptr

std :: unique_ptr представляет данные, которые имеют только одного владельца в любой момент времени. Это должно быть вашим выбором по умолчанию, когда вам нужен умный указатель. Вы можете перемещать std :: unique_ptr , чтобы поддерживать его в рабочем состоянии, но может быть только один владелец данных.После перемещения указателя предыдущий объект указателя становится недействительным.

Существует также тип std :: unique_ptr , который представляет массивы. Я склонен придерживаться обычного типа std :: unique_ptr и использовать std :: vector или std :: array в тех случаях, когда я хочу иметь дело с массивами.

Вы захотите использовать std :: unique_ptr в таких случаях, как:

  • Динамическое распределение памяти, доступ к которому одновременно осуществляется только в одной области (можно перемещать)
    • Буферы для USB-передачи
    • Распределение локальных объектов (для больших объектов, которые вам не нужны в стеке)
    • Распределение по потокам
  • Заводская функция вывода (т.е. уникальных экземпляров)
  • Члены класса, являющиеся указателями

std :: shared_ptr

Вы должны использовать std :: shared_ptr , когда есть совместное владение объектом. std :: shared_ptr использует подсчет ссылок и уничтожает объект, когда нет используемых экземпляров. В основном я использую std :: shared_ptr для совместного использования объектов между потоками. Однако убедитесь, что каждый поток имеет свой собственный std :: shared_ptr , а не использует один и тот же!

Обратите внимание, что использование std :: shared_ptr может усложнить отслеживание вашего кода, поскольку время жизни объекта может быть не сразу очевидным для других разработчиков, просматривающих ваш код.Не используйте std :: shared_ptr , если достаточно std :: unique_ptr .

std :: weak_ptr

Вы должны использовать std :: weak_ptr , если вы хотите проверить или использовать ресурс разделяемой памяти, но не хотите нести ответственность за поддержание данных в рабочем состоянии, внося свой вклад в счетчик ссылок. std :: weak_ptr также полезен в ситуациях, когда ваша программа будет реагировать по-разному в зависимости от того, жив ли ресурс.

Я видел, как многие обсуждали использование std :: weak_ptr для разрыва цикла, который поддерживал бы ваши объекты (например, в связанном списке), но я не сталкивался с такими проблемами в моем собственном коде.

Основной случай, когда я избегаю интеллектуальных указателей, — это дизайн API. Если базовая функция не станет владеть данными интеллектуального указателя, мои API-интерфейсы в основном используют необработанные указатели или ссылки (поскольку они не могут быть NULL ). Однако вы должны быть уверены, что переданный вами необработанный указатель не переживет контейнер интеллектуального указателя.

Поскольку интеллектуальные указатели являются индикаторами владения данными, я стараюсь избегать их, когда данные не принадлежат мне. Такой случай возникает при ссылке на объекты, владеющие текущей областью (например,грамм. «Родительские» указатели). Если родительский объект владеет текущей областью и имеет гарантированное существование, используйте ссылку. Если родительский объект владеет вами, но существует вероятность отсутствия владельца, используйте указатель.

Хотя я не думаю, что память или эксплуатационные расходы интеллектуальных указателей имеют значение, если ваша система достаточно ограничена, вам нужно будет учитывать накладные расходы на объект std :: shared_ptr (требования к памяти блока управления и операции подсчета ссылок).

Переход с C на C ++ Статьи

Связанные

Умные указатели на C ++.Умный указатель — это объект класса, который… | автор: Nishi Tyagi

Умный указатель — это объект класса, который действует как указатель, но имеет некоторые дополнительные функции.

Например: в функции ниже:

Нормальные указатели

Каждый раз, когда эта функция вызывается, она выделяет память из кучи, но никогда не освобождает память. Мы можем разобраться в этом, добавив перед оператором return один дополнительный оператор:

delete ps;

Мы должны постоянно помнить о распределении памяти.

Предположим, перед удалением ps , если возникнет какое-то исключение, мы не сможем удалить эту память.

Обычные указатели с оператором удаления.

Когда функция func завершится, все локальные переменные будут удалены из стека. Память, занятая указателем ps , будет освобождена, но было бы неплохо, если бы память, указанная указателем ps , также была освобождена.Если у ps был деструктор, то мы можем освободить память, на которую указывает ps , поэтому основная проблема — ps — это только указатель, а не объект класса, имеющий деструктор.

Это идея интеллектуальных указателей😃.

Интеллектуальный указатель

Итак, интеллектуальные указатели подобны объектам-указателям, в которых деструктор вызывает удаление, когда указатель выйдет за пределы области видимости.

Пример использования auto_ptr

Если p1 и p2 были обычными указателями, то два указателя будут указывать на один и тот же строковый объект, и программа попытается удалить один и тот же объект дважды, один раз, когда p1 будет выйти за рамки, а другой, когда p2 выйдет за рамки.

Здесь p2 получает право собственности на объект, а p1 теряет право собственности, поэтому теперь ответственность за удаление этого объекта лежит на p2 .

Но что произойдет, если программа попытается использовать данные, указанные p1 ??

Рассмотрим следующий пример:

Пример использования auto_ptr

Произойдет ошибка сегментации в обоих примерах .. !!!

Здесь идет уникальный указатель на рисунке:

Unique_ptr

«Если программа пытается назначить один unique_ptr другому, компилятор разрешает это, если исходный объект является временным rvalue, и запрещает его, если источник объект имеет некоторую продолжительность.”

Уникальный указатель

Если программе требуется более одного указателя для объекта, следует использовать общий указатель .

shared_ptr использует подсчет ссылок. Для каждого нового указателя на тот же объект счетчик будет увеличиваться на единицу и уменьшаться на единицу, если срок действия указателя истечет. Когда окончательный указатель истечет, будет вызвано удаление.

Примечание:

1 . Стандарт C ++ 11 сделал auto_ptr устаревшим.

2. Функция std :: move () может разрешить присвоение одного unique_ptr другому.

Путь вперед : семантика перемещения и ссылка на rvalue.

Спасибо за чтение !! 😃

M.1 — Введение в интеллектуальные указатели и семантику перемещения

Рассмотрим функцию, в которой мы динамически выделяем значение:

void someFunction ()

{

Resource * ptr = new Resource (); // Ресурс — это структура или класс

// здесь что-то делать с ptr

delete ptr;

}

Хотя приведенный выше код кажется довольно простым, довольно легко забыть освободить ptr.Даже если вы не забыли удалить ptr в конце функции, существует множество способов, которыми ptr не может быть удален, если функция завершается раньше. Это может произойти за счет досрочного возврата:

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

#include

void someFunction ()

{

Resource * ptr = new Resource ();

int x;

std :: cout << "Введите целое число:";

std :: cin >> x;

если (x == 0)

возврат; // функция возвращается раньше, и ptr не будет удален!

// делаем что-нибудь с ptr здесь

delete ptr;

}

или через выброшенное исключение:

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

#include

void someFunction ()

{

Resource * ptr = new Resource ();

int x;

std :: cout << "Введите целое число:";

std :: cin >> x;

if (x == 0)

выбросить 0; // функция возвращается раньше, и ptr не будет удален!

// делаем что-нибудь с ptr здесь

delete ptr;

}

В двух вышеупомянутых программах выполняется ранний оператор return или throw, в результате чего функция завершается без удаления переменной ptr.Следовательно, теперь происходит утечка памяти, выделенной для переменной ptr (и будет происходить утечка снова каждый раз, когда эта функция вызывается и возвращается раньше).

По сути, такого рода проблемы возникают из-за того, что переменные-указатели не имеют встроенного механизма очистки после себя.

Классы умных указателей спешат на помощь?

Одна из лучших особенностей классов заключается в том, что они содержат деструкторы, которые автоматически запускаются, когда объект класса выходит за пределы области видимости.Поэтому, если вы выделяете (или приобретаете) память в своем конструкторе, вы можете освободить ее в своем деструкторе и гарантировать, что память будет освобождена, когда объект класса будет уничтожен (независимо от того, выходит ли он за пределы области видимости, удаляется явно, так далее…). Это лежит в основе парадигмы программирования RAII, о которой мы говорили в уроке 11.9 — Деструкторы.

Итак, можем ли мы использовать класс, чтобы помочь нам управлять указателями и очищать их? Мы можем!

Рассмотрим класс, единственной задачей которого было удерживать и «владеть» переданным ему указателем, а затем освобождать этот указатель, когда объект класса выходит за пределы области видимости.Пока объекты этого класса создавались только как локальные переменные, мы могли гарантировать, что класс правильно выйдет за пределы области видимости (независимо от того, когда и как завершаются наши функции) и принадлежащий ему указатель будет уничтожен.

Вот первый набросок идеи:

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

37

38

39

40

41

42

#include

template

class Auto_ptr1

{

T * m_ptr;

public:

// Передаем указатель на «own» через конструктор

Auto_ptr1 (T * ptr = nullptr)

: m_ptr (ptr)

{

}

// Деструктор сделает убедитесь, что он освобожден

~ Auto_ptr1 ()

{

delete m_ptr;

}

// Перегрузите разыменование и оператор->, чтобы мы могли использовать Auto_ptr1 как m_ptr.

T & оператор * () const {return * m_ptr; }

T * оператор -> () const {return m_ptr; }

};

// Пример класса для доказательства вышеизложенного работает

class Resource

{

public:

Resource () {std :: cout << "Ресурс получен \ n"; }

~ Resource () {std :: cout << "Ресурс уничтожен \ n"; }

};

int main ()

{

Auto_ptr1 res (new Resource ()); // Обратите внимание на выделение памяти здесь

//… но явное удаление не требуется

// Также обратите внимание, что для ресурса в фигурных скобках не нужен символ *, поскольку он предоставляется шаблоном

return 0;

} // здесь res выходит за рамки и уничтожает выделенный нам ресурс

Эта программа напечатает:

 Ресурс получен
Ресурс уничтожен
 

Рассмотрим, как работают эта программа и класс. Сначала мы динамически создаем ресурс и передаем его в качестве параметра нашему шаблонному классу Auto_ptr1.С этого момента наша переменная Auto_ptr1 res владеет этим объектом Resource (Auto_ptr1 имеет композиционные отношения с m_ptr). Поскольку res объявлен как локальная переменная и имеет область видимости блока, она выйдет из области видимости, когда блок закончится, и будет уничтожен (не беспокойтесь о том, чтобы забыть освободить его). И поскольку это класс, при его уничтожении будет вызван деструктор Auto_ptr1. Этот деструктор гарантирует, что указатель ресурса, который он удерживает, будет удален!

Пока Auto_ptr1 определен как локальная переменная (с автоматической продолжительностью, отсюда «Авто» часть имени класса), Ресурс будет гарантированно уничтожен в конце блока, в котором он объявлен, независимо от того, как функция завершается (даже если завершается раньше).

Такой класс называется интеллектуальным указателем. Интеллектуальный указатель — это класс композиции, который предназначен для управления динамически выделяемой памятью и обеспечения удаления памяти, когда объект интеллектуального указателя выходит за пределы области видимости. (Соответственно, встроенные указатели иногда называют «тупыми указателями», потому что они не могут убрать после себя).

Теперь вернемся к нашему примеру someFunction () выше и покажем, как класс интеллектуального указателя может решить нашу задачу:

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

37

38

39

40

41

42

43

44

45

46

49

0002 47

00030002 47

0003

51

52

53

54

#include

template

class Auto_ptr1

{

T * m_ptr;

public:

// Передаем указатель на «own» через конструктор

Auto_ptr1 (T * ptr = nullptr)

: m_ptr (ptr)

{

}

// Деструктор сделает убедитесь, что он освобожден

~ Auto_ptr1 ()

{

delete m_ptr;

}

// Перегрузите разыменование и оператор->, чтобы мы могли использовать Auto_ptr1 как m_ptr.

T & оператор * () const {return * m_ptr; }

T * оператор -> () const {return m_ptr; }

};

// Пример класса для доказательства вышеизложенного работает

class Resource

{

public:

Resource () {std :: cout << "Ресурс получен \ n"; }

~ Resource () {std :: cout << "Ресурс уничтожен \ n"; }

void sayHi () {std :: cout << "Привет! \ N"; }

};

void someFunction ()

{

Auto_ptr1 ptr (new Resource ()); // ptr теперь владеет ресурсом

int x;

std :: cout << "Введите целое число:";

std :: cin >> x;

if (x == 0)

return; // функция возвращает ранний

// делаем что-нибудь с ptr здесь

ptr-> sayHi ();

}

int main ()

{

someFunction ();

возврат 0;

}

Если пользователь вводит целое число, отличное от нуля, вышеуказанная программа напечатает:

 Ресурс получен
Привет!
Ресурс уничтожен
 

Если пользователь вводит ноль, вышеуказанная программа прекращает работу раньше, выводя:

 Ресурс получен
Ресурс уничтожен
 

Обратите внимание, что даже в случае, когда пользователь вводит ноль и функция преждевременно завершается, ресурс все равно освобождается должным образом.

Поскольку переменная ptr является локальной переменной, ptr будет уничтожен при завершении функции (независимо от того, как она завершится). И поскольку деструктор Auto_ptr1 очистит Ресурс, мы уверены, что Ресурс будет очищен должным образом.

Критический недостаток

Класс Auto_ptr1 имеет критическую ошибку, скрывающуюся за некоторым автоматически сгенерированным кодом. Прежде чем читать дальше, посмотрите, сможете ли вы определить, что это такое. Подождем…

(Подсказка: подумайте, какие части класса генерируются автоматически, если вы их не предоставляете)

(Музыка Jeopardy)

Хорошо, время вышло.

Вместо того, чтобы рассказывать вам, мы вам покажем. Рассмотрим следующую программу:

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

#include

// То же, что и выше

template

class Auto_ptr1

{

T * m_ptr;

общедоступный:

Auto_ptr1 (T * ptr = nullptr)

: m_ptr (ptr)

{

}

~ Auto_ptr1 ()

{

удалить m_ptr;

}

T & оператор * () const {return * m_ptr; }

T * оператор -> () const {return m_ptr; }

};

class Resource

{

public:

Resource () {std :: cout << "Ресурс получен \ n"; }

~ Resource () {std :: cout << "Ресурс уничтожен \ n"; }

};

int main ()

{

Auto_ptr1 res1 (new Resource ());

Auto_ptr1 <ресурс> res2 (res1); // В качестве альтернативы не инициализируйте res2, а затем назначьте res2 = res1;

возврат 0;

}

Эта программа напечатает:

 Ресурс получен
Ресурс уничтожен
Ресурс уничтожен
 

Очень вероятно (но не обязательно) ваша программа выйдет из строя на этом этапе.Теперь видите проблему? Поскольку мы не предоставили конструктор копирования или оператор присваивания, C ++ предоставляет их нам. А функции, которые он предоставляет, делают мелкие копии. Поэтому, когда мы инициализируем res2 с помощью res1, обе переменные Auto_ptr1 указывают на один и тот же ресурс. Когда res2 выходит за пределы области видимости, он удаляет ресурс, оставляя res1 висящим указателем. Когда res1 удаляет свой (уже удаленный) ресурс, происходит сбой!

Вы столкнетесь с аналогичной проблемой с такой функцией:

void passByValue (Auto_ptr1 res)

{

}

int main ()

{

Auto_ptr1 res1 (new Resource ());

passByValue (res1)

return 0;

}

В этой программе res1 будет скопирован по значению в параметр res passByValue, что приведет к дублированию указателя ресурса.Крушение!

Итак, очевидно, что это нехорошо. Как мы можем решить эту проблему?

Что ж, одна вещь, которую мы могли бы сделать, — это явно определить и удалить конструктор копирования и оператор присваивания, тем самым предотвращая создание любых копий в первую очередь. Это предотвратит передачу по значению (что хорошо, мы, вероятно, все равно не должны передавать их по значению).

Но как же тогда вернуть Auto_ptr1 из функции обратно вызывающей стороне?

??? generateResource ()

{

Resource * r = new Resource ();

возврат Auto_ptr1 (r);

}

Мы не можем вернуть наш Auto_ptr1 по ссылке, потому что локальный Auto_ptr1 будет уничтожен в конце функции, а вызывающая сторона останется с висящей ссылкой.Возврат по адресу имеет ту же проблему. Мы могли бы вернуть указатель r по адресу, но потом мы могли бы забыть удалить r позже, в чем и заключается весь смысл использования интеллектуальных указателей в первую очередь. Так что вышло. Возвращение Auto_ptr1 по значению — единственный вариант, который имеет смысл, но тогда мы получаем неглубокие копии, дублированные указатели и сбои.

Другой вариант — переопределить конструктор копирования и оператор присваивания для создания глубоких копий. Таким образом, мы, по крайней мере, гарантированно избежим дублирования указателей на один и тот же объект.Но копирование может быть дорогостоящим (и может быть нежелательным или даже невозможным), и мы не хотим делать ненужные копии объектов только для того, чтобы вернуть Auto_ptr1 из функции. Кроме того, присвоение или инициализация тупого указателя не копирует объект, на который указывает, так почему же нам ожидать, что умные указатели будут вести себя иначе?

Что нам делать?

Семантика перемещения

Что делать, если вместо того, чтобы наш конструктор копирования и оператор присваивания копировали указатель («семантика копирования»), мы вместо этого передаем / перемещаем владение указателем от источника к объекту назначения? Это основная идея семантики перемещения. Семантика перемещения означает, что класс передаст право собственности на объект, а не сделает копию.

Давайте обновим наш класс Auto_ptr1, чтобы показать, как это можно сделать:

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

37

38

39

40

41

42

43

44

45

46

49

0002 47

00030002 47

0003

51

52

53

54

55

56

57

58

59

60

61

62

63

9 0002 64

65

#include

template

class Auto_ptr2

{

T * m_ptr;

общедоступный:

Auto_ptr2 (T * ptr = nullptr)

: m_ptr (ptr)

{

}

~ Auto_ptr2 ()

{

удалить m_ptr;

}

// Конструктор копирования, который реализует семантику перемещения

Auto_ptr2 (Auto_ptr2 & a) // примечание: не const

{

m_ptr = a.m_ptr; // переносим наш тупой указатель из источника в наш локальный объект

a.m_ptr = nullptr; // убеждаемся, что источник больше не владеет указателем

}

// Оператор присваивания, реализующий семантику перемещения

Auto_ptr2 & operator = (Auto_ptr2 & a) // примечание: не const

{

if (& a == this)

return * this;

удалить m_ptr; // убедитесь, что мы освободили любой указатель, который адресат уже удерживает, первый

m_ptr = a.m_ptr; // затем переносим наш тупой указатель из источника в локальный объект

a.m_ptr = nullptr; // убеждаемся, что источник больше не владеет указателем

return * this;

}

T & оператор * () const {return * m_ptr; }

T * оператор -> () const {return m_ptr; }

bool isNull () const {return m_ptr == nullptr; }

};

class Resource

{

public:

Resource () {std :: cout << "Ресурс получен \ n"; }

~ Resource () {std :: cout << "Ресурс уничтожен \ n"; }

};

int main ()

{

Auto_ptr2 res1 (new Resource ());

Auto_ptr2 res2; // Начинаем как nullptr

std :: cout << "res1 is" ​​<< (res1.нулевой() ? "null \ n": "не null \ n");

std :: cout << "res2 is" << (res2.isNull ()? "Null \ n": "not null \ n");

res2 = res1; // res2 предполагает владение, res1 устанавливается равным нулю

std :: cout << "Право собственности передано \ n";

std :: cout << "res1 is" ​​<< (res1.isNull ()? "Null \ n": "not null \ n");

std :: cout << "res2 is" << (res2.isNull ()? "Null \ n": "not null \ n");

возврат 0;

}

Эта программа напечатает:

 Ресурс получен
res1 не равно нулю
res2 имеет значение null
Право собственности передано
res1 имеет значение null
res2 не равно нулю
Ресурс уничтожен
 

Обратите внимание, что наш перегруженный оператор = передал право владения m_ptr от res1 к res2! Следовательно, мы не получаем дубликатов указателя, и все аккуратно очищается.

std :: auto_ptr, и почему этого следует избегать

Сейчас самое подходящее время поговорить о std :: auto_ptr. std :: auto_ptr, представленный в C ++ 98, был первой попыткой C ++ создать стандартизованный интеллектуальный указатель. std :: auto_ptr решил реализовать семантику перемещения, как это делает класс Auto_ptr2.

Однако std :: auto_ptr (и наш класс Auto_ptr2) имеет ряд проблем, делающих его использование опасным.

Во-первых, поскольку std :: auto_ptr реализует семантику перемещения через конструктор копирования и оператор присваивания, передача std :: auto_ptr по значению функции приведет к тому, что ваш ресурс будет перемещен в параметр функции (и будет уничтожен в конце функция, когда параметры функции выходят за рамки).Затем, когда вы переходите к аргументу auto_ptr от вызывающей стороны (не осознавая, что он был передан и удален), вы внезапно разыменовываете нулевой указатель. Крушение!

Во-вторых, std :: auto_ptr всегда удаляет свое содержимое, используя удаление без массива. Это означает, что auto_ptr не будет правильно работать с динамически выделяемыми массивами, потому что он использует неправильный тип освобождения. Хуже того, это не помешает вам передать ему динамический массив, которым он затем будет неправильно управлять, что приведет к утечке памяти.

Наконец, auto_ptr плохо сочетается со многими другими классами стандартной библиотеки, включая большинство контейнеров и алгоритмов.Это происходит потому, что эти классы стандартной библиотеки предполагают, что при копировании элемента фактически создается копия, а не перемещение.

Из-за вышеупомянутых недостатков std :: auto_ptr устарел в C ++ 11 и не должен использоваться. Фактически, std :: auto_ptr планируется полностью удалить из стандартной библиотеки как часть C ++ 17!

Правило: std :: auto_ptr устарело и не должно использоваться. (Вместо этого используйте std :: unique_ptr или std :: shared_ptr). .

Движение вперед

Основная проблема с дизайном std :: auto_ptr заключается в том, что до C ++ 11 в языке C ++ просто не было механизма, позволяющего отличить «семантику копирования» от «семантики перемещения».Переопределение семантики копирования для реализации семантики перемещения приводит к странным крайним случаям и непреднамеренным ошибкам. Например, вы можете написать res1 = res2 и не знать, изменится ли res2 или нет!

Из-за этого в C ++ 11 была формально определена концепция «перемещения», и в язык была добавлена ​​«семантика перемещения», чтобы правильно отличать копирование от перемещения. Теперь, когда мы подготовили почву для понимания того, почему семантика перемещения может быть полезной, мы исследуем тему семантики перемещения в оставшейся части этой главы.Мы также исправим наш класс Auto_ptr2, используя семантику перемещения.

В C ++ 11 std :: auto_ptr был заменен набором других типов интеллектуальных указателей, «учитывающих перемещение»: std :: unique_ptr, std :: weak_ptr и std :: shared_ptr. Мы также рассмотрим два самых популярных из них: unique_ptr (который является прямой заменой auto_ptr) и shared_ptr.

интеллектуальных указателей — 1.61.0

интеллектуальных указателей — 1.61.0

Введение
Общие требования
Безопасность исключений
Спецификации исключений
История и благодарности
Ссылки

Интеллектуальные указатели — это объекты, которые хранят указатели на динамически выделяемые (куча)
объекты.Они ведут себя так же, как встроенные указатели C ++, за исключением того, что они
автоматически удалить объект, на который указали, в нужное время. Умный
указатели особенно полезны перед исключениями, поскольку они обеспечивают
правильное уничтожение динамически размещаемых объектов. Их также можно использовать для
отслеживать динамически размещаемые объекты, принадлежащие нескольким владельцам.

Концептуально интеллектуальные указатели рассматриваются как владеющие указанным объектом и, следовательно,
отвечает за удаление объекта, когда он больше не нужен.

Библиотека интеллектуальных указателей предоставляет шесть шаблонов классов интеллектуальных указателей:

Эти шаблоны разработаны для дополнения шаблона std :: auto_ptr .

Это примеры идиомы «получение ресурса — это инициализация».
описано в Бьярне Страуструпе «Язык программирования C ++», 3-е издание,
Раздел 14.4, Управление ресурсами.

Кроме того, библиотека интеллектуальных указателей обеспечивает эффективные фабричные функции.
для создания объектов интеллектуального указателя:

Тестовая программа smart_ptr_test.cpp, это
предоставляется для проверки правильности работы.

Страница совместимости со старыми версиями
библиотека интеллектуальных указателей Boost описывает некоторые изменения, произошедшие с более раннего
версии реализации умного указателя.

Будет интересна страница с таймингами умных указателей.
для тех, кто интересуется проблемами производительности.

Страница со списками методов программирования интеллектуальных указателей
некоторые продвинутые приложения shared_ptr и weak_ptr .

Эти шаблоны классов интеллектуальных указателей имеют параметр шаблона, T , который
указывает тип объекта, на который указывает умный указатель. Поведение
шаблонов интеллектуальных указателей не определено, если деструктор или оператор удаляют
для объектов типа T выдают исключения.

T может быть неполным типом в точке объявления интеллектуального указателя.
Если не указано иное, требуется, чтобы T был полным типом на
точки инстанцирования умного указателя.Реализации необходимы для диагностики
(рассматривать как ошибку) все нарушения этого требования, включая удаление
неполный тип. См. Описание
checked_delete шаблон функции.

Обратите внимание, что shared_ptr не имеет этого ограничения, так как большинство
его функции-члены не требуют, чтобы T был полным типом.

Обоснование

Требования к T тщательно разработаны для обеспечения максимальной безопасности, но позволяют
ручка-тело (также называемое pimpl) и подобные идиомы.В этих идиомах умный
указатель может появиться в единицах перевода, где T — неполный тип.
Это отделяет интерфейс от реализации и скрывает реализацию от
единицы перевода, которые просто используют интерфейс. Примеры описаны в
документация по конкретным интеллектуальным указателям иллюстрирует использование интеллектуальных указателей в
эти идиомы.

Обратите внимание, что scoped_ptr требует, чтобы T был полным типом на
время уничтожения, а shared_ptr нет.

Некоторые функции в этих классах интеллектуальных указателей указаны как не имеющие
эффект «или» без эффекта, кроме такого-то «, если выбрасывается исключение.
означает, что когда объект одного из этих классов вызывает исключение,
все состояние программы остается таким же, как было до вызова функции
что привело к возникновению исключения. Это составляет гарантию того, что
нет заметных побочных эффектов.Другие функции никогда не вызывают исключений.
Единственное исключение, которое когда-либо создавалось функциями, которые выбрасывают (при условии, что T соответствует
общие требования): std :: bad_alloc ,
и это вызывается только функциями, которые явно задокументированы как
возможно, бросая std :: bad_alloc .

Исключения-спецификации не используются; видеть
обоснование исключительной спецификации.

Все шаблоны интеллектуальных указателей содержат функции-члены, которые никогда не могут
исключения, потому что они не генерируют исключения сами и не вызывают другие
функции, которые могут вызывать исключения.Эти участники обозначены комментарием:
// никогда не выбрасывает
.

Запрещены функции, уничтожающие объекты указанного типа.
выбрасывание исключений по общим требованиям.

История и благодарность

, февраль 2014 г. Глен Фернандес обновил перегрузки make_shared и
allocate_shared в соответствии со спецификацией стандартного документа C ++
[D & F-14] и реализовал make_unique для
массивы и объекты.Питер Димов и Глен Фернандес обновили скаляр и
реализации массивов, соответственно, для устранения дефекта стандартной библиотеки C ++
2070.

, ноябрь 2012 г. Глен Фернандес предоставил реализации make_shared
и allocate_shared для массивов. Они достигают единовременного распределения на
массив, который может быть инициализирован аргументами конструктора или списками инициализаторов
а также перегрузки для инициализации по умолчанию и без инициализации значения.См. Make_shared и allocate_shared для
страницу массивов для получения дополнительной информации.

Январь 2002 г. Петр Димов переработал все четыре класса, добавил функции, исправил
bugs, разбив их на четыре отдельных заголовка и добавив weak_ptr .
См. Страницу совместимости для краткого обзора
изменения.

май 2001 г. Владимир Прус предложил потребовать полный тип при уничтожении.
Уточнение эволюционировало в обсуждениях, включая Дэйва Абрахамса, Грега Колвина, Бемана.
Доус, Райнер Дейк, Питер Димов, Джон Мэддок, Владимир Прус, Шанкар Сай и
другие.

, ноябрь 1999 г. Дарин Адлер предоставил operator == , operator! = и std :: swap
и std :: less специализаций для общих типов.

, сентябрь 1999 г. Луис Коэльо предоставил shared_ptr :: swap и shared_array :: swap

Май 1999 года. В апреле и мае 1999 года Валентин Боннар и Дэвид Абрахамс провели
количество предложений, приводящих к многочисленным улучшениям.

, октябрь 1998 г. Беман Доус предложил возродить исходную семантику под
имена safe_ptr и countted_ptr , встреча Пера Андерссона, Мэтта
Остерн, Грег Колвин, Шон Корфилд, Пит Беккер, Нико Йосуттис, Дитмар Кюль,
Натан Майерс, Чичианг Ван и Джуди Уорд. В ходе обсуждения четыре новых
доработаны названия классов, решено, что точно нет необходимости
следуйте интерфейсу std :: auto_ptr , а также различным сигнатурам функций и
семантика доработана.

В течение следующих трех месяцев было рассмотрено несколько реализаций для shared_ptr ,
и обсуждались в списке рассылки boost.org.
Вопросы реализации вращались вокруг счетчика ссылок, который должен быть
сохранены, либо прикреплены к указанному объекту, либо отсоединены в другом месте. Каждый из
у этих вариантов есть два основных варианта:

  • Прямое отключение: shared_ptr содержит указатель на объект и указатель
    к графу.
  • Косвенное отсоединение: shared_ptr содержит указатель на вспомогательный объект, который
    в свою очередь содержит указатель на объект и счетчик.
  • Встроенный прикрепленный: счетчик является членом указанного объекта.
  • Размещение прикреплено: счет прикреплен с помощью новых манипуляций оператора.

Каждый метод реализации имеет свои преимущества и недостатки.Мы зашли так далеко
как использовать различные тайминги прямого и косвенного подходов, и обнаружил, что
по крайней мере, на чипах Intel Pentium разница была очень незначительной.
Кевлин Хенни предоставил статью, которую он написал, «Техники счетного тела». Дитмар
Кюль предложил элегантную технику частичной специализации шаблонов, позволяющую
пользователям выбирать, какую реализацию они предпочитают, и это также было
экспериментировал.

Но Грег Колвин и Джерри Шварц утверждали, что «параметризация помешает
пользователей », и в конце концов мы решили предоставить только прямую реализацию.

Лето 1994 г. Грег Колвин предложил Комитету по стандартам C ++ классы с именем auto_ptr
и countted_ptr , которые были очень похожи на то, что мы сейчас называем scoped_ptr
и shared_ptr . [Col-94] В одном из очень немногих
случаи, когда рекомендации Рабочей группы библиотеки не были выполнены
полный комитет, countted_ptr был отклонен и удивительно
Семантика передачи права собственности была добавлена ​​в auto_ptr .

[D & F-14] Питер Димов и Глен Фернандес,
Расширение make_shared для поддержки массивов, редакция 1, документ комитета C ++ N3870,
Январь, 2014.

[Col-94] Грегори Колвин,
Исключительные безопасные интеллектуальные указатели, документ комитета C ++ 94-168 / N0555,
Июль 1994 г.

[E & D-94] Джон Р. Эллис и Дэвид Л. Детлефс,
Безопасный и эффективный сборщик мусора для C ++, Usenix Proceedings,
Февраль 1994 г.В этом документе подробно обсуждаются слабые указатели.
и обширная библиография.


$ Дата $

Copyright 1999 Грег Колвин и Беман Доус. Copyright 2002 Дарин Адлер.
Распространяется по лицензии Boost Software, версия 1.0. См. Сопроводительный
файл LICENSE_1_0.txt или скопируйте на
http://www.boost.org/LICENSE_1_0.txt.

CppCon 2020: расписание

CppCon 2020: расписание

09:00 MDT

09:00 MDT

09:00 MDT

09:00 MDT

12:00 MDT

08:45 MDT

10:30 MDT

12:00 MDT

13:30 MDT

14:30 MDT

15:00 MDT

07:30 MDT

09:00 MDT

10:00 MDT

10:05 MDT

10:30 MDT

11:35 MDT

12:00 MDT

13:00 MDT

13:05 MDT

13:30 MDT

15:00 MDT

07:30 MDT

09:00 MDT

10:00 MDT

10:30 MDT

12:00 MDT

13:05 MDT

13:30 MDT

14:10 MDT

14:40 MDT

15:00 MDT

15:45 MDT

16:30 MDT

07:30 MDT

08:40 MDT

09:00 MDT

10:05 MDT

10:30 MDT

12:00 MDT

13:30 MDT

14:45 MDT

15:00 MDT

15:45 MDT

16:00 MDT

16:15 MDT

07:45 MDT

08:00 MDT

09:00 MDT

10:00 MDT

10:30 MDT

12:00 MDT

13:00 MDT

13:30 MDT

15:00 MDT

08:00 MDT

09:00 MDT

09:00 MDT

09:00 MDT

C ++ 11_smart_ptrs.pdf — Использование интеллектуальных указателей C 11 Дэвид Кирас Департамент EECS Мичиганского университета, июнь 2016 г. В этом руководстве рассматривается интеллектуальный указатель C 11

Использование интеллектуальных указателей C ++ 11 Дэвид Кирас, Департамент EECS, Мичиганский университет, июнь 2016 г. интеллектуальный указатель, который состоит из unique_ptr, shared_pt и его партнера, weak_ptr и некоторых связанных функций и классов шаблонов. См. Опубликованные примеры кода для примеров, представленных здесь. Концепция интеллектуальных указателей C ++ 11 Умные указатели — это объекты класса, которые ведут себя как встроенные указатели, но также управляют объектами, которые вы создаете с помощью new, поэтому вам не нужно беспокоиться о том, когда и удалять ли их — интеллектуальные указатели автоматически удаляют управляемый объект за вас в подходящее время.Интеллектуальный указатель определяется таким образом, что его можно синтаксически использовать почти так же, как встроенный (или «необработанный») указатель. Таким образом, вы можете использовать их в значительной степени, просто подставляя объект интеллектуального указателя везде, где код использовал бы необработанный указатель. Интеллектуальный указатель содержит встроенный указатель и определяется как шаблонный класс, параметр типа которого является типом указанного объекта, поэтому вы можете объявлять интеллектуальные указатели, указывающие на объект класса любого типа. Когда дело доходит до динамически выделяемых объектов, мы часто говорим о том, кто «владеет» объектом.«Владение» чем-либо означает, что это ваше право сохранить или разрушить, как вы считаете нужным. В C ++ под владением мы подразумеваем не только то, какой код должен ссылаться на объект или использовать его, но в основном то, какой код отвечает за его удаление. Если интеллектуальные указатели не задействованы, мы реализуем владение с точки зрения того, где в коде мы размещаем удаление, которое уничтожает объект. Если мы не сможем правильно реализовать владение, мы получим утечку памяти или неопределенное поведение при попытке следовать указателям на объекты, которые больше не существуют.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *