Подготовка к собеседованию на C/C++ Developer
Менторы
Специалисты своей области, которые смогут помочь вам
Middle .Net Developer
Senior Product Manager
Middle Python Developer
Ведущий программист
Backend Software Engineer (PHP)
Senior .NET/C# developer
Middle DevOps Engineer | Tbilisi, Georgia
Middle C# .NET
Senior PHP-разработчик
Middle python developer
Каналы
Полезные Telegram каналы и чаты
Транскрипция видео:
так Ну тогда давай начнем уже перейдем собственно к интервью значит Давай начнем с того что поговорим об умных указателях как они там появлялись может быть в истории их появления вообще зачем они появлялись может быть про эволюцию их какую-то что-то знаешь вот расскажи то что знаешь указатели появились чтобы обезопасить разработчика при написании программ от того чтобы он не забывал очищать выделенную память на них перекладывалась ответственность за автоматическое освобождение памяти после выхода из зоны видимости например
00:00:00 - 00:01:29
соответственно первый указать может быть не первый но из тех что я знаю указатель был авто ПТР который был впоследствии за причине того что в общем если было два овнера и один из этих холмеров вызывал деструктор а нет при копировании этого указателя то есть в этом автопатере не поддерживал семантика копирования и поэтому при копировании указателя другому огнеру тот первый указатель оставался пустым да Ну в принципе да это правильно до 1 То есть первый указатель он был уже не валиным объектом по сути с ним уже
00:00:50 - 00:02:18
ничего нельзя было делать Да и что приводила Там ошибкам окей что ему на смену пришло ему на смену пришел дневник ПТР это указатель который нельзя было указать владельца у него не было следующего года но подожди Правильно ли высказывание о том что нельзя сменить владельца точнее Как сменить владельца можно но через да то есть программист когда пишет именно перемещает владение объектом То есть он делает это явно явно Я просто имел ввиду что у него может быть только один владелец ты сказал про мусульманку сказал
00:01:41 - 00:03:33
Расскажи что такое семантика зачем она нужна Как как ее использовать она нужна для того чтобы наши какие-то операции по перемещению не были слишком дорогими То есть когда мы например хотим скопировать большой объем данных перенести его куда-то в другое место нам проще передать как бы указатели на этот объект на эти объекты вот Не перемещая сами объект Именно для этого была создана Ну да ладно хорошо нормально так Окей что у нас есть помимо Питера еще какие у нас есть умные указатели или даже не подвиг но они как бы вместе
00:02:44 - 00:04:19
работают Ну это да Окей как у нас работает какие там ты вообще использовал Питер там где-то было бы что-то такое Ну там где Я использовал там принципе можно было юник использовать Ну в общем как бы расскажу иметь указательный объект нескольким оумером При этом когда все овнеры выходят из зоны видимости внутри него есть счетчик ссылок который эти ссылки деграрементируют и когда этот счетчик становится память указывающая память которая была выделена и на которой указывали Да окей давай как раз мы заговорили
00:03:43 - 00:05:19
счетчике ссылок и всем подобным давай как раз таки первое наше задание с тобой будет сегодня это именно мы с тобой реализуем ты реализуешь начинать [музыка] моего будем реализовать Окей тогда такой русские буквы Так что нам нужно для него нам для него нужен конструктор так Ну давай у нас sharpointer он все-таки будет нормальный в том плане что он у нас будет шаблоны Так давай начнем наверное с двумя тут у нас подсветка синтаксиса Так что ты если видишь он как не выделяет ошибка а ты знаешь какой вообще тип обычно
00:04:43 - 00:06:12
используется для каунтеров вообще все плюс плюс таких вещей наверное да давай так поехали значит Кислотный конструктор не передается И мы должны пронициализировать наши две переменных поскольку то ничего передать придется то Pointer инициализируем смотрим аккаунт это что какой тип данных Ну да аккаунт пока еще у нас ПТР то есть мы должны тогда сделать сайт Подожди кнт Вот именно сенти вот это Стоп стоп стоп Вот так мы теперь вызвали как бы конструктор сайдсти который передали А для чего для чего Нам нужен
00:06:44 - 00:08:20
для чего нам хранить вообще каунтер если у нас нету Питера по сути как бы можно тоже вот именно состояние объекта шара Питер то есть нулевое состояние непонятно зачем нам хранить выделять память под аккаунтер если у нас нету самого объекта имею на которой мы ссылаемся поэтому тут по сути тоже по сути указатель на сайте а тогда тебе вопрос 14 15 ракеты написал что равно 0 Для чего ты написал но мы можем Ничего здесь не написать тогда это подразуме будет подразумеваться что здесь будет какой-то дефолтное значение
00:08:03 - 00:09:38
Но тогда под него может выделиться какая-то память А нам это не надо мы хотим явно чтобы эти перемены были про непроницаемость как раз таки ты пишешь инициализацию когда ты пишешь равно 05 правильно Но тогда насколько я понимаю никакая память не выделится и нет подожди попеременные под кнт ptr под именно как члены класса под них выделится парень в любом случае если у нас Какие есть варианты не написать ничего То есть просто аккаунты все тогда будет насколько я понимаю на это все на лодку компилятора и там по идее будут какие-то
00:08:58 - 00:10:28
дефолтные значения вообще компилятор не гарантирует на них полагаться не стоит поэтому все ну мне вообще вопрос Чему был просто получается что на седьмой строке инициализации на 14 15 по сути ты просто лежишь код здесь Потому что это одно и то же то есть нас Мы когда пишем в членах класса то если мы не инициализируем после двоеточие в этих местах то они принимают именно те значения которые мы задали по умолчанию Поэтому я считаю что вот эта часть тут как бы как будто бы не нужна совсем когда может быть есть смысл написать
00:09:43 - 00:11:02
просто или в этом тоже нет смысла Ну равно дефолт можно да Вполне себе равно дефолда так тогда нам теперь нормальный конструктор вот здесь вот мы уже должны пронициализировать как-то кажется что да единицы мы выделим правильности и так далее дальше как дальше что он так правило пяти значит конструктор есть обычно конструктор есть теперь нужно поддержать семантику копирования семантику перемещения нам нужно для этого написать копи-конструктор для начала Давай напишем так еще час Так мы расшарили значит указатели
00:10:30 - 00:12:16
счетчик вроде все так Идем дальше Теперь нам точно точно ли все что у нас Что у нас по счетчикам ссылок получается В каком случае мы вызываем кооператор конструктор копирования Мы хотим скопировать хотим еще один создать еще один да тогда нам нужно взять значение от нашего Да а что если у нас у другой пойнтер Он пустой если он пустой то вот этих полей вот эти поля будут равны Ничего здесь ничего здесь не будет тогда Ну тогда по идее это вот эта штука должна проигнорировать просто Почему Сейчас она у тебя не игнорируется сейчас
00:13:26 - 00:15:14
она не игнорируется Тогда нужно то есть если указатель из Теперь теперь мы конструктор здесь мы но по сути то же самое капсом писать продолжаешь кричать так это есть и так если Так мы моем здесь в этом случае значит мы должны тот объект В общем мы должны Короче занулить все вот эти два значения указатель и счетчик для чего мы это делаем потому что мы если мы перемещаем указатели на объект Это мы должны очистить эти указатели сменили владельца допустим изменили Да но просто типа не будем дальше пользоваться например этим
00:14:56 - 00:16:52
указателем для чего Кроме того что это может быть семантически есть прям четкая причина Зачем нам нужен Ну если мы оставим как бы не зануленным то тот указатель старый так и будет указывать Ну так и пусть он указывает вообще проблем нет с тем что он указывает как будто бы Ладно Хорошо давай давай мы дальше пойдем дальше я думаю Понятно Будет Почему операторов вообще Какое возвращаемое значение я так скажу там точно не будут там точно не был Никак а вообще там специальная вещь но там не просто так для того чтобы например
00:17:39 - 00:19:11
Давайте скажу там ссылка на самом деле На текущий объект возвращается А для чего это сделано как думаешь Ну мы же получается присваиваем то есть тот объект он должен получить ссылку на то что мы присвоили по идее Ну это ты говоришь про это понимаю аргумент вот напиши вот просто сигнатуру вот Мы понимали что мы понимаем Да ну только что-то перебор Так есть да И вот вопрос был в том для чего нам здесь нужно нужны нужно возвращать им на ссылку так Ну ладно если знаешь пойти дальше тут вообще на самом деле для того чтобы
00:19:17 - 00:20:57
использовать в течение присваивании то есть когда у нас идет там например возьмем то вообще ну как вот есть у нас например они равно B равно 3 мы можем так написать Вот по сути для этого и тоже используется у нас возвращаем значение в качестве ссылок Да да конечно так просто по сути выполнить копирование данных из одного указателя в другой близкое к тому что мы делали так А если у нас это был последний допустим получается Мы потеряем наш Питер если это был последний мы потеряем Почему получается мы указываем на допустим у
00:20:52 - 00:22:42
нас есть когда мы оператор присваивания означает то что у нас объект уже существует верно в этом плане мы тогда так же как в конструкторе должны проверить указатель Да это кажется вообще не проблема Ну Питер Ну смотри у нас есть наш Давай напишем там От чего там будет да И тут какой-нибудь int там 5 допустим 6 и мы создаем допустим создаем еще такой же второй похоже там семерка Пусть отличается и вот мы хотим P1 сделать равно P2 вот что произойдет с памятью которая с указателем который вот этот который я
00:22:26 - 00:24:14
выделил на сороковой строке в твоем коде он получается Но получается это будет утечка то есть мы потеряем просто этот указатель Тогда нужно перед этим сначала очистить что-то только не передается после этого нужно почистить память у того указателя Ну то есть почистить вот эти поля у него такая аккаунта давай почистим а это не слышал такой вещи как свободе Мы например не слышал как раз можно насколько я помню менять владельца вообще есть ушат по интернет просто нет на свой путем это именно короче Почитай потом это именно способ
00:23:29 - 00:25:02
как можно написать операторы присваивания причем там со всякими плюшками по типу обеспечения исключений [музыка] мы делаем это пока не будем делать Просто а так что должен мы должны Counter занулить наверное сейчас наверное не забывать вообще что он скаутер это тоже [музыка] Counter это у нас какой тип Но вообще Конечно вот это сработает Но это семантически выглядит неверно Ну вот сейчас мы именно адрес указателя мы должны сам указательным кажется что это нам вообще не то что нам нужно [музыка]
00:24:28 - 00:26:12
не-не-не это не то вообще не про это Смотри вот еще зануд питерел Питер Ну окей ты за занулил чисто Вот именно член класса Питер Ну а указатель то он все равно он существует же Ну я имею ввиду не указатели область памяти которая выделена Ну то есть его надо насколько разумно использовать фри если мы выделяли память под ним это оператор поэтому какие есть два Делика только на которой ты который ссылается потому указателю которому передалит массиву удаляет какой-то диапазон Вроде так это работает ну плюс
00:25:55 - 00:27:23
да так OK В общем заделители наверное вот здесь тоже надо для аккаунта заделить потому что там что тоже мы делали да наверное надо опять кричишь получается моих почистилизировали значениями мы так смотрю мы сейчас взяли за делители того кто кого мы копируем это как нормально Мы же сначала скопировали то есть мы Ну на же нему семантику мы копируем смотри у нас в аргументах передан другой кастом шар Питер правильно и ты сейчас на 31 строке и 33 строке ты берешь и делитесь именно с того с кого мы копируем зачем
00:27:18 - 00:29:09
нам это делать тогда нам получается здесь [музыка] вообще не совсем правильно было делить после Давай еще раз разберемся в чем тут у нас проблема что нам нужно поделить вот если мы смотрим наш пример который мы не написал получается у нас P1 [музыка] P1 есть какой-то Питер есть какой-то кнт и наверное их нужно и поделить которые на которые он сейчас указывает на шестерку которую он сейчас указывает их нужно поделить и перед тем как наверное копировать из другого объекта тогда делаем вот так Теперь я понял И у тебя все равно
00:28:51 - 00:30:24
смотреть мы потому что сначала делить им потом присваиваем там ничего нет но это тоже но мы опять таки также продолжаешь делить эти чем-то более другого объекта из которого мы копируем мы другой объект Это даже никак не скомпилируется почему это не скомпилируется как ты думаешь потому что берем не какой-то конкретный смотри мы принимаем Пеппа какой процентной ссылке как мы вообще можем что-то делать с полями другого класса которую мы принимаем по константной ссылке Ну давай ладно чтобы мы тут не долго не
00:30:08 - 00:31:29
заседали мы должны поделить эти не ПЭК этот кнт мы должны кнт текущие от This потому что мы копируем сюда в него поэтому мы должны поделить кнт и ПТР который у текущего объектов которые мы копируем потому что нам эти данные больше не нужны но мы должны кажется что не надо вообще ничего присваивать лучшим полям Нет давай вот этому уберем присваивание тут вопрос именно в освобождении памяти вот Окей [музыка] поэлементно поинтер и Counter где все да Ну конечно да в том примере который мы не это будет работать нормально но что
00:30:58 - 00:32:24
если мы напишем [музыка] допустим int но я к тому что сейчас у нас явно Это плохо работает копии P1 и мы скопируем Сейчас я тебе скажу как Мы это сделаем [музыка] P1 хорошо вот у нас существует копии P1 и мы делаем вот эту вот да по сути все вот я тебе точно говорю здесь будут проблемы у нас будут проблемы [музыка] Ну вот написано что такое это который скопировал один Ну то есть при этом скопировал ну подожди с конструктором копирования У нас все нормально строке все должно быть нормально Вот я
00:32:26 - 00:34:43
тебе уверяю что после 52 строки [музыка] у нас будут проблемы В текущей реализации даже Давай скажу Так у нас будут проблемы с купе P1 то есть мы попробуем Достучаться до его Питера то у нас скорее всего будет очень плохо давай так хорошо что мы тоже не заседали сейчас на этом проблем тут том что когда ты будешь на 52 строки из подвал копировать P1 и мы зайдешь на 29 30 строку Ты просто да высвободишь аккаунтеры пойнтер и копии P1 который указывал на те же конторы Pointer просто будут получаться не валидный указатели
00:33:45 - 00:35:24
мы должны в этом случае проверить если вообще что-то мы должны проверить прям что там Да я бы сказал так если там Не ну ПТР то или наоборот Давай мы сейчас Давай мы сейчас вообще вот это немножко оставим оставим наш конструктор Ой не конструктора оператор присваивания копирование Давай мы с тобой напишем инструктор потому что мне кажется это может нам помочь если у нас то есть высвобождаем ресурс Ну да Ну плюс-минус конечно да но а если у нас каунтер если у нас пустой шар от поинтер перед высвобождением что
00:34:45 - 00:36:18
у нас здесь тогда произойдет мы тогда должны еще проверить что произойдет будет ошибка какая именно не помню Ну смотри у нас аккаунт получается будет обращение ты будешь разминовывать нулевой указатель [музыка] такого А И у нас еще нужно будет сам А что будет если мы делить им Ну Питер Ну что но память на которую ссылается этот указатель но у нас Я говорю у нас Питер это ну Питер делаем Что происходит Нет он не равен не я это вообще просто в целом вопрос как бы произойдет ошибка доступа к данным то есть мы пытаемся вызвать
00:36:57 - 00:38:35
деструктор несуществующего объекта 05 То есть он как бы отличается от Free тем что кроме того что освобождает ресурс он еще и вызывает инструктор объект А поскольку под Питера никакого объекта у нас нет А если не помню как правильно выглядит Ну Фред Ну ничего не произойдет разрешает Да ну окей допустим на общем По моему я честно Ладно сам сейчас подзабыл мне казалось что по моему делит одну Питер и тоже ничего не произойдет типа он разрешает там перегрузка скорее всего какая-то так Окей ну я говорил про каунт у нас все
00:38:05 - 00:39:34
равно здесь в есть возможность разуменовать есть вероятность что мы заменуем нулевой указатель если он правильно создан и у него в этот момент то может быть здесь буквально буквально вот так вот мы сейчас сделаем вот так просто я тебе скажу что вот тут будет нулевое нулевого указателя то есть вызовется Тогда нужно сначала проверить их Аккаунт что ли то есть вообще если Такой тип надо проверить наверное каунту что он равен Питеру или нет да да сначала проверяем его потом деградируем потом уже Чистим сам указатель вот так
00:38:59 - 00:40:58
Ну да Ну пойдет ладно да так вот наша конструктор дерево возвращаемся к оператору присваивания кажется что вначале нужно сделать что-то похожее на тогда получается надо сделать просто вызвать деструктор что ли целиком Ну вообще Ну вообще Вызвать дестру Не очень но мы можем принципе ладно почему нет ну то есть мы по сути должны повторить Здесь тоже самое получится мы должны очистить Ну давай так так Окей мы вызвали мы вызвали и присвоили новые значения и теперь Так мы вызвали приствольного значения
00:40:30 - 00:42:15
теперь надо со счетчиком сделать проинкомментировать его смотри если у нас вот такая вещь даже не такая а вот такая тогда будет два дефолтных объекта У нас вот у нас получается [музыка] Ну да правильно значит в чем проблема значит что надо сделать Но с другой стороны мы не очистим ее потому что аккаунт будет равен у ПТР Но мы вот эту штуку нам нужно ли очищать вопрос блин походу Нет потому что это все просто перезапишется вообще Ну короче мой понял В том что наверное вообще не нужно ничего делать если
00:41:32 - 00:43:00
нам Если мы самого себя самого себя копируем то есть это типа как частный случай Если да Я просто подумал что Идем дальше а если у нас Пепе равен 10r OK [музыка] Но если это будет равен то мы ничего не делаем Но тогда у нас Ну да все нормально Ну да ладно окей Да окей давай дальше теперь в конструкторе мы должны вот так вот сделать еще [музыка] кстати говоря Пока сейчас писал я посмотрел на оператор присваивания мы там все равно кое-что не сделали мы там давайте сразу скажу мы не увеличили счетчик ссылок Да да я про
00:42:56 - 00:44:40
него сказал забыл так то есть мы это будем делать любом случае что ли Да окей так делать Так что у нас мы имеем мы имеем мы имеем так какие у нас еще методы есть которые нам нужны для того чтобы это был полноценный Так у нас пам что есть у нас есть конструктор копирование конструктор перемещения У нас есть сайт копирование саймоном перемещения и деструктор есть Так Ну для того чтобы просто это был Давай чтобы шар Питер который можно было что-то делать что нам не хватает нам не хватает доступа хотя бы
00:45:28 - 00:47:01
гитар и там собственно шар Питер есть смотри метод у нас что это просто у нас указатель возвращает указатель да [музыка] а что ты знаешь о константных не константных методах константные методы не позволяют менять атрибуты этого объекта которым они живут вот Get у нас это константный должен быть метод или нет да константный Константа еще тогда вопрос методах Nox Слышал такое слово знаешь слышал но не очень понимаю то есть видимо там для каких-то случаев актуально писать новой except тоже не помню Для каких видимо Судя по названию
00:46:42 - 00:48:22
он пропускает Exception В каких случаях метод внутри этого метода все что происходит но вообще нет не совсем если у нас метода говорит эпилятору что этот метод не выбрасывает исключение он не генерирует дополнительный код для это такая оптимизация Вот Но если мы вылетает нас эксепшен метода то это сразу аборт то есть мы даже не сможем вот а вопрос такой тогда выкидывать исключение из конструкторов это как нормально можно Нет это не нормально то есть потому что это не нормально потому что в таком случае будет не
00:48:01 - 00:49:33
неопределенное поведение с точки зрения инструктора То есть если мы выкинем исключения то мы сможем потом вызвать деструкторы будут утечка Ну вообще говоря вообще говоря Нет на самом деле из конструктора исключение выбрасываются просто надо в конструкторе грамотно это делать Хорошо давай деструкторе можно выкидывать исключения по той же логике Я считаю что не стоит потому что если ты на каком-то этапе выкинешь исключение то например дочерних например инструкторы то есть не надо если коротко Ну да вообще говоря деструкты у нас не
00:48:51 - 00:50:11
явно определенно как Nox то есть компилятор сам его определяет там на самом деле больше проблема в том что когда у нас Мы кетчем какой-то кетчем какое-то исключение если у нас там процессе еще выкинете из деструктора у нас начнется стекан rapping Знаешь такой мы пойдем дальше исключение у нас начинается вот и вызывать деструкторы А если у нас во время стакан рапинг вылетает исключение из деструктора то мы вообще никак не сможем словить Вот И поэтому это будет да Окей так это мы обсудили давай смотри что давай знаешь
00:49:50 - 00:51:22
Ну да Ну расскажи что это такое вообще есть какие-то плюсы и использования Что круче использовать может быть вообще что она делает давать для начала определимся Make shareit она как бы делает дает указатель То есть можно создать умный указатель через конструктор можно через Майк шерсть и по идее считается насколько я читал что через лучше но я не помню почему могу попробовать вспомнить [музыка] Ну давай хотя бы Давай попробуем хотя бы успеть сигнатуру функции написать это обычная функция поэтому ее вне
00:50:53 - 00:52:12
класса определяем она будет возвращать ссылку на объект вообще она возвращается не ссылку она возвращает просто пойнтер А да она просто возвращает экземпляр так сюда просто Смотри не совсем она так вообще работает это не работал так понимаю Да или как Ну я просто им пользовался никогда Ну смотри там не совсем так там получается не ограниченное количество аргументов то есть неопределенные варианты слышал такую сталкивался то есть вот такую может быть так вообще говоря у нас это должен быть сейчас эти напишу сигнатуру
00:51:39 - 00:53:25
нет нет ну ладно дальше наверное смысла нету с этим возиться OK а слышал что нибудь про стеде Форвард [музыка] нет по моему Но это что-то про инкрементацию что ли чего-то Нет В общем не слышал план потом Почитай это идеальная передача реализует такую как бы паттерн так тогда математика у нас с тобой была что ты можешь сказать что вообще делает [музыка] переназначает указатель то есть переназначает адреса другому указателю прямо берет и что-то кому-то указывает что-то меняет не совсем так на самом деле просто
00:53:18 - 00:55:03
кастет рвал ее ссылки и не более того по сути ничего такого не делает Я не понял спасибо Ну вот так Так у нас еще три минуты Так мы поговорили до про это про это смотри еще у нас в реализации Бага есть синтаксическая наверное все таки на 8 строке там у нас Это не совсем так делается Ну короче нам не хватает а еще у меня вопрос Например у нас 17 строке у нас конструктор перемещение правильно как вот это что такое вообще как бы вопрос аргумент а Можем ли мы передать лвл ю в такую функцию на самом деле можем
00:54:27 - 00:56:12
это называется универсальная ссылка может быть слышал когда-то то есть это по сути когда мы говорим о [музыка] об аргументах функции именно 2 имперсанта то это универсальная ссылка тоже почитай там потом про универсальные ссылки вот А почему тогда вопрос сюда попадает только рвл ее ссылки вот у нас ну то есть я вот я сказал что мы можем сюда передать Но почему тогда мы делаем у нас называется именно этот конструктор для чего это происходит Ну тут вопрос в том что это перегрузка функции просто по сути
00:56:03 - 00:57:27
поэтому когда он видит и видит что у нас есть более приближенный Ну да это тоже там есть большое количество перегрузке компилятор выбирает именно более близкий более подходящий Вот это тоже можно почитать посмотреть Ну собственно что у нас время уже подо
00:56:47 - 00:57:33