interview_json.txt
Document Details
Uploaded by Deleted User
Full Transcript
\[ { "Sergei": "Tch, shsh. What? Олег, добрый день. Да, привет. Слышь на меня, да, хорошо. Так, сейчас минутку. Тоже включу камеру. Окей. Так, да, слышь на меня, нормально? Да, слышу, как меня. Да, тоже хорошо слышу. Так, сейчас ставлю запись. так вроде запись пошла так сегодня мы хотим пройти вот п...
\[ { "Sergei": "Tch, shsh. What? Олег, добрый день. Да, привет. Слышь на меня, да, хорошо. Так, сейчас минутку. Тоже включу камеру. Окей. Так, да, слышь на меня, нормально? Да, слышу, как меня. Да, тоже хорошо слышу. Так, сейчас ставлю запись. так вроде запись пошла так сегодня мы хотим пройти вот пройти по первому этапу вопросы посмотреть вас прошу о обсуждать их вот давай тогда начнем вот ну первый просто такой не вопрос да и даже не знаю не то чтобы обсуждать а просто как что тебе если ты допустим плохо ориентируешься там остальные фишки, может быть, ну имеет смысл просто посмотреть там, да, например, там, ну что в 11-14-17-й, вот, ну хотя бы примеры в голове держать, какие там вещи появились, да, вот, ну просто посмотришь, потом и всё, сейчас-то не будем там на этом заострять внимание, вот, давай вот промные указатели, я не знаю, насколько детально вот на собеседу не обсуждали, так как нет, я тебя собеседовал, да? Вот, давай быстрее попробуем пройтись. Какие есть умные указатели и в чём отличие там основного?" }, { "Oleg": "Так, ну умные указатели есть Unique Pointer, Shared Pointer, Unique Pointer и Up Pointer это как бы стареющий старый. Значит, Shared Pointer предполагает совместное овладение объектом. Unique Pointer предполагает уникальное овладение объектом. Ну то есть один владелец, других владелец может быть не может. Соответственно, для юник-поинтера, если нам надо передать владение, мы его передаем, то есть оно передается для шарит-поинтера. У нас, соответственно, несколько владельцев, и объект будет существовать в памяти до тех пор, пока у нас последний владелец, да, не освободить этот ресурс, то есть не исчезнет там, допустим, из-за области видимости. Тогда будет продолжать существовать этот объект памяти. Так, у нас ещё есть BigPointer. Но это такой слабый указатель, за чём предназначен. Возникают иногда такие циклические ссылки. И для того, чтобы избежать циклических ссылок у нас применяется BigPointer. То есть BigPointer что позволяет вам из себя, из BigPointer позволяет. сделать шарит-поинтер, то есть из него преобразовать шарит-поинтер, но тогда уже шарит-поинтер, дальше как-то, соответственно, уже как шарит-поинтер, да, живет. Так, и автопоинтер. Автопоинтер это старая, устарившая конструкция, то есть стандарты 98-го соответственно. Поэтому да, можно про нее и не говорить, потому что депрекетит, вот у нас три основных, давай их вот еще обсудим. Получается, что, ну какой эффективник, юник или шея, в плане скорости работы?" }, { "Sergei": "Эффективник, конечно, юник, потому что ему не надо держать, вот этот вот разделяемый счетчик ссылок, поэтому юник, это происходит, ну то еще он эффективнее, быстрее. И вот ты сказал, что Ну, юник, я так понимаю, что ты имеешь в виду, что не копируемый, да? Ты говорил просто фразу, я забыл копируемый." }, { "Oleg": "Да, мы передаем владению, то есть там мы уже... один юник-поинтер присвоить другому юник-поинтеру, то есть передать как бы дату про владение. Ну, то есть исходный, где был объект, он соответственно передаст владению другой." }, { "Sergei": "То есть, мов-мов сделать." }, { "Oleg": "Да, либо через муф, да, это через муф. Я так сейчас, по-моему, через конструктор там, по-моему, не прокатит." }, { "Sergei": "Ну, конечно, да, не прокатит. То есть это, ну, копирование, по сути, да, получится." }, { "Oleg": "Да-да-да, и присваивание, соответственно, тоже через муф." }, { "Sergei": "Окей, вот еще, вот в шарит-пойнтере, да, вот ты говоришь, что еще чики там, ссылок и так далее, вот это все как-то устроено. То есть какие там поля в этом шарит-пойнтере, как и беспечивается разделение самого объекта и где хранится и в каком виде, вот еще очень ссылок." }, { "Oleg": "Так, ну счетчик ссылок, то есть если мы попросту представим себе этот шарит-поинтер, то соответственно внутри шарит-поинтера есть поле, ну пусть это будет поле типа, который мы там храним, это указатель, собственно, а второе поле -- это поле там сайст-т или имп можно, но не важно там со самым подходом, пусть это будет там сайст-т, то есть это тоже указатель, который соответственно являются указателем и поэтому по адресу этого указателя хранится то количество ссылок, которые на этот шарит-поинтер в текущий момент ссылаются, то есть количество экземпляров шарит-поинтера, который владеет этим объектом." }, { "Sergei": "Да, здесь вот важный то, что ты сказал, что там сначала-то сказал сайс-т, потом ты сказал указатель. Важно, что именно указатель, потому что он тоже должен быть разделяемым." }, { "Oleg": "То есть это с IST указатель, мы его тоже через New выделяем. И соответственно, когда мы инициализируем объект через New, он у нас принимает значения единички. Соответственно, мы, допустим, создаем еще один Shared Pointer, который, ну, является, разделяет тот же самый объект, соответственно, у нас в Count, про вот эту щетку величиваться на единичку. Если у нас какой-то шарит поинтер, ну, выходит из области видимости, а у него вызывается деструктор, соответственно, каунтер уменьшается. Если у нас отработал последний деструктор, то есть, когда у нас каунтер до нуля сократился, то мы удаляем объекты с поинтерами." }, { "Sergei": "Да, ну вот тут не совсем так, на самом деле. Во-первых, там не просто сайс-т по указателю. Там лежит контрол-блок, так называемый, а в нем несколько полей, то есть вот этот счетчик-сылок, он называется счетчик сильных ссылок, про который ты говоришь. Там же есть еще счетчик слабых ссылок, который увеличивает и уменьшает ВИК-ПТР. То есть, у тебя хранится не просто сайс-т, а специальная структура по этому указателю. Там лежит два счетчика, Сильных ссылок, слабых ссылок, также там лежит еще кое-что. Как ты думаешь, что? А может еще лежать?" }, { "Oleg": "Ну ладно долго не будем потому что надо там проходиться это ну дилитер еще может быть костомный дилитер у таких вещей как шальд птр вот у них есть там костомный дилитер да который позволяет с разными типами ресурсов нам работать по сути ну указатель на удаляющую функцию там может быть например ну в целом там конструктор просто не думал что это лежит именно в разделяемом ну вот в этой самой до структурки" }, { "Sergei": "Ну вот это вспомогательная техническая структура, в которой хранится счетчик сильных ссылок, слабых ссылок и еще кастомный дилитер, который позволяет работать с разными типами ресурсов." }, { "Oleg": "Да, ну иначе придется его хранить в каждом шарит-поторе, это как бы..." }, { "Sergei": "Да, ну да, иначе он будет хранить, да, тогда действительно это не эффективно. То есть, ну да, надо там хранить. Второй вопрос, который ты, как сказать, не совсем корректно говоришь, то, что если счетчик сильных ссылок обнуется, то объект и ресурс будет освобожден. Это не всегда так. Есть тонкий момент. в функции MakeShare. Когда ты создаешь Shared PTR через MakeShare, то она имеет такую особенность, что она делает одно выделение памяти вместо двух. Когда ты создаешь через New, у тебя идет выделение памяти под объект, конструирование объекта. Потом выделение памяти под CtrlBlock и, соответственно, у тебя два выделения памяти. Когда ты делаешь MakeShare, функцию вызываешь, что у тебя делается одно выделение памяти под размер памяти, который туда влезает и объект, и CtrlBlock в один блок памяти. Вот, это такая оптимизация. Но эта оптимизация имеет такую особенность, что если у тебя есть Вик ПТР, и на этот шарит ПТР, и при этом счетчик сильных ссылок обнулился, ты не можешь взять и освободить память. Точнее, у тебя ресурс освободится, у тебя диструктор объекта вызвается, но память вот эта вот вся, которая выделена в том числе и под объект, не только под CtrlBlock, но и под объекта. Она не будет особо ждать. Допустим, если у тебя есть большой объект, с которым ты работаешь, создав его через MakeShare, при этом используешь ВикПТР, то когда ты освободишь последний шарит ПТР, у тебя объект уничтожится, но не от гарантии, ну как бы не то, что не от гарантии, а у тебя точно память не освободится. Вот это такой тонкий момент, который часто нам спрашивают, например, на собесах, что именно, может быть, минусом использования MakeShare. Какая особенность?" }, { "Oleg": "Получается еще тогда утечка памяти или что?" }, { "Sergei": "Нет, когда ВикПТР последнее освободится, ну ты же не можешь освободить память, почему? Потому что у тебя там лежит щечек ВикПТР, в которой как бы считают эти слабые ссылки. Когда он обнулится, то у тебя вся память будет освобождена." }, { "Oleg": "У дечки памяти нет. Я просто для себя немножко, то есть получается в расчет идут ну как бы оба варианта счетчика ссылок и сильных и слабых, как только оба обнуляются, тогда все-таки память освобождается. Именно когда мы работаем через Майк Шерт. Почему так? Потому что они лежат, мы не можем эту память освободить, она выделена одним Нью. Если мы ее освободим, получается у нас Вик ПТР, которые существуют, они будут в какую-то освобожденную память ссалаться. Понимаешь?" }, { "Sergei": "Вот еще против функции MakeShare и MakeUnique. Они, как бы, исходно создавались еще для одной цели. Вот MakeShare мы сказали про оптимизацию с одним выделением памяти, но есть еще одна фишка, связанная с исключениями. Ты знаешь?" }, { "Oleg": "Нет" }, { "Sergei": "Смотри вот есть такая вещь как undefined behavior а есть unspecified behavior вот unspecified behavior это не ужасная вещь какая-то как undefined behavior да unspecified behavior это такой пример например что порядок подсчета аргументов функции не определен например у тебя вызывается функция f а в ней допустим ua ub да и вот неизвестно какой из этих нею вызовется первым то же самое работает если ты напишешь там f она у тебя допустим первый аргумент шарит ptr ua а второго аргумента шарит ptr ub вот неизвестно какой порядок будет может сначала вызываться ua потом ub потом конструктор шарит ptr для ua а потом конструктор шарит ptr для ub получается, что если у тебя в конструкторе B кинулась исключение, но у тебя A уже выделилась, память выделилась, объект создался, но он не обернулся еще в шарит PTR, и таким образом будет и утечка памяти, и утечка ресурсов. Из-за вот такой особенности. Функции makeShared и makeVenue позволяют этого избежать нам. Если мы напишем в качестве аргументов makeShared, makeSharedA, makeSharedB, то у тебя не будет такой ситуации, у тебя гарантированно, как бы они обернутся, не будет утечки, но после 17-го стандарта этот порядок более детерминированный стал, и такой проблему больше нет. То есть MakeUnique нам больше ни для чего не нужен на самом деле. MakeUnique создавался только для этого, но после 17-го стандарта и эта функция не нужна. То есть он по сути сейчас просто нам позволяет более красивый код писать, не используя Нью, скажем, вот это, наверное, единственная его фишка в самых последних стандартах. Еще последний вопрос про умные указатели. Как ты считаешь, можно ли приобрезовать UniquePtr в SharePtr?" }, { "Oleg": "Нужно извлечь указатель, чтобы он вернул нам указатель, но отказался от владения этим указателем. Соответственно, для шарит ПТИР, надо будет подсунуть этот указатель, но этот способ такой не очень хороший, что он немного противоречит. То есть, сделать можно, но это противоречит раи, ресурсы, локейшн и занициализации. То есть, у нас должна быть... при инициализации должна быть аллакукация, то есть в принципе ответ да можно да можно но неправильно ты описал есть проблема с тем подходом который ты сказал потому что у нас есть дилитер у нас может быть дилитер кастомный какой уник птера так и у шельг птера то есть" }, { "Sergei": "ну а дилитер то мы что же можем извлечь и передать" }, { "Oleg": "ну насчет извлечь интересный вопрос на самом деле у шельг птер ну по сути у него просто есть специальный конструктор который принимает уник птер если ты просто муваешь туда и уник птер и все и он сам вытащит и дилитер тебе короче все сделает" }, { "Sergei": "это не знам то есть у иник у шарит птера то есть у него есть да такой специальный конструктор для инициал" }, { "Oleg": "ага да ну да этот способ который я говорил там дилитер да мы получаются можем потом ну то есть получить проблему получить проблему есть дилитер кастомный вот давай дальше пойдем тогда вот есть такая вещь как лямда функции да с ними работаешь вообще" }, { "Sergei": "ну так приходилось работать с лямда функциями ну вот что в итоге из нее получается когда ты пишешь лямда функцию как бы а что она конвертится вообще это" }, { "Oleg": "Можно считать, что это нечто нам дано, от языка начиная с одиннадцатого стандарта. То есть пострепа поддерживается на уровне средств языка, поэтому я могу сказать, почему она приближённая, потому что ничего реально там, если оно поддержано на уровне языка, без всяких библиотек, то там уже куда глубже копать. Это очень наполненнает указатель на функцию, то есть по сути как бы функтор или указатель на функцию или функция, который можно передать аргументы и она вернёт определённый результат. Я так себе это понимаю, вот у нее же есть более фишечка с захватом, да, вот блок захвата там есть, и тогда..." }, { "Sergei": "Ну да, если говорить еще про лямда-функцию, там, помимо параметров, которые она принимает, да, у нее есть еще, что ее отвечает там от функции, да, у нее есть блок захвата, то есть это квадратные скобочки, и в этот блок захвата можно передать Ну, переменные, которые видны в текущем области видимости до определения ландо-функции. Туда можно передать как по ссылке, так и по значению. Ну, да, есть там всякие нюансы, то есть, по сути, у нас будет передано по значению, то есть, если мы передаем по значению, потом что-то меняем. В общем, там контекст сохраняется, копируется, то есть, каждая лямба получит. то значение, которое было до ее визуализации обновления. Но это тонкости я уже..." }, { "Oleg": "Ну вот, просто могут спросить, в каком все-таки случае Лиамда функция просто может быть преобразованного обычную функцию?" }, { "Sergei": "Ну, в самом простом случае это, конечно, когда у нас..." }, { "Oleg": "А, когда без этих самых... Когда без вот этих вот без захвата, без кавычек." }, { "Sergei": "Да, можно, как обычная функция." }, { "Oleg": "Кстати, да, все было такой опыт, да. Надо было и в сишный код передавать. И как раз без... без групп захвата все хорошо работало, но только появлялась стишный код отказался с этим работать." }, { "Sergei": "Да, потому что там в класс преобразуются. Ну, как по сути в класс. Так, окей, дальше пойдем. Давай представим, что у нас есть две коллекции. Одна это список интов лист. Вот, а вторая массив просто интов. Одинаковых значений. Вот мы по обоим этим коллекциям пробегаемся и складываем значение. Вот с каким контейнером будет быстрее работать?" }, { "Oleg": "По поем коллекции пробегаемся и там читаем значение или складываем." }, { "Sergei": "Да, складываем. Хотим получить сумму всех элементов." }, { "Oleg": "А, складываем в этом контейнер. Чисто алгоритмически казалось бы, что и там, и там у нас должна быть одинаковая производительность. Смотреть сухую теорию по алгоритму, то есть в грядуческой сложности она будет одинаковая, но с точки зрения производительности, который уже на аппаратную часть завязана, более эффективно будет работать с динамическим массивом с вектором, потому что тут вопрос того, что у него не прерывная область памяти, а у списка она разрознена, то есть состоит из указателей, которые взаимоввязаны между собой, и поэтому она разрознена, то есть она может находиться в разных сегментах, разных блоках, а единый блок памяти это более эффективно с точки зрения кишей процессоров." }, { "Sergei": "Да, то есть на самом деле там разница на порядке может быть вот в десять раз может быть больше чем в десять раз по скорости да согласен так так давай вот про STD-set и on-order-set в чем их разницей на основе чего каждый сделан" }, { "Oleg": "так STD-set это по сути Дерево, в данном случае, может сказать, порядочная, наверное, бинарная, красно-черная, наверное, так назовем этот тип дерева." }, { "Sergei": "Ну, часть всего, да, да." }, { "Oleg": "На основе красно-черного деревья есть там" }, { "Sergei": "А? В чём хишка этого дерева?" }, { "Oleg": "Фишка этого дерева устроена так, что у него есть ведка ведущая на лево, ведка ведущая на право, элементы, которые меньше текущего они находятся с левой, те, которые больше текущего они находятся с правой. То есть по сути оно упорядочено таким образом и обеспечивает нам определенную производительность по операциям." }, { "Sergei": "Да, важное свойство просто не упоминаешь, то, что оно сбалансированное." }, { "Oleg": "А да, плюс еще дерево красный-шорное, оно определенным образом сбалансировано, то есть у него фактически, по-моему, высота дерева пропорциональна логорифмом от n, ну там по-моему с каким-то эффициентом 2, что ли?" }, { "Sergei": "Ну да, там могут быть тонкости, но по сути нам это обеспечивает логорифмические операции." }, { "Oleg": "Нам это обеспечивает логорифмическую сложность по операциям, связанным с этим видом контейнера. Так, идём дальше со NordertMap, точнее NordrCet. В основе NordrCet у нас лежит такая сущность, как hashTabLitza. Соответственно, главным атрибутом такой структуры данных, как hashTabLitza, является hashFunction. Соответственно, hashFunction обеспечивает некое равномерное распределение. Некого числа на определенном интервале и как это примерно работает, хэш-функция, то есть мы имеем какое-то значение, например строку, которая является элементом анордроцепт, то есть элементом хэш-таблицы. На основе для строки рассчитывается ее хэш, и хэш по хэшу на основе операции модуля определяется в бакет в котором должна находиться это это значение соответственно попадаем в бакет вот и в бакете уже хранится само само вот это значение могу добавить еще что бывает коллизии то есть так что хэш функция дает То, что для разных строк у нас будет вычислено одно и то же значение хэша. Соответственно, мы попадем в одно и то же, в один и тот же бакет. Это будет состояние коллизии. Но коллизии, соответственно, каким образом избегаются. То есть, внутри бакетов, в зависимости от реализации, там самая простая реализация, это дальше список хранится. То есть, мы дополнительно еще в бакете проходимся по списку для того, чтобы найти или убедиться, что в бакете есть нужное для нас значение. Вот по операциям алгоритмической сложности здесь у нас обеспечивается константная алгоритмическая сложность, то есть мы по сути за константное время имеем доступ к элементу, но за счет хэширования бакетов. Если у нас есть как бы самый худший случай, когда у нас плохая хэш-функция, тогда у нас просто наша хэш-таблица, она выродится в список, то есть мы будем иметь линейную сложность относительно. работы, то что по элементам." }, { "Sergei": "Да, отлично. Почти все вопросы ответил сам. Вот есть еще такая вещь, как лод фактор. Знаешь, что это?" }, { "Oleg": "Да, есть так называемый лод фактор. Он колеблется. Ну, нормальным значением является 0,65-0,75. То есть это по сути соотношение количества бакетов к количеству элементов, которые у нас хранится в хэштаблице. В общем, когда оно специально сделано чуть меньше, чтобы эта вероятность коллизий, у нас шубак, было чуть больше, чем элементов, чтобы снизить вот эти вероятности коллизий. Значит, когда у нас load factor, он переходит за определенное ну вот эту границу, там 0.65 на 0.75, у нас происходит рехэш. Ну, то есть, по сути, это примерно как с динамическим массивом мы там переиненциализируем. Ну, просим себе больше памяти уделяем и копируем туда элементы массива. Здесь то же самое, то есть, происходит рехеш, мы запрашиваем больше количества памяти, мы пересчитываем, теперь уже на новое соотношение количества бакетов, мы пересчитываем хыши, от хышей, соответственно, мы пересчитываем остаток по модулю, ну, чтобы пересчитать, да, в такие бакеты мы должны попасть теперь новые. Ну, и, соответственно, туда мы перекладываем. наши наши значения из старой хэштаблицы в новую хэштаблицу, которую уже с новым лот фактором окей, окей так значит, еще вот пару вопросов на тему всяких вот этих сложностей вот случай с вектором ты тоже сказал, что там похожая ситуация, то есть обычно у нас допустим пушбек у него какая сложность как считается" }, { "Sergei": "константная сложность, в принципе, когда мы добавляем, у нас есть какой-то запас там сзади, и у нас туда вставляется за линейную сложность, но когда там заканчивается место, соответственно, мы, исходя из стратегии увеличения размера, как правило, это уношение на два, мы запрашиваем новую память перекладываем в новую выделенную память элементы с старой память, с старой память освобождаем и добавляем в конец новый элемент, тут, да, тут мы в линейную попадаем в сложность, но она считается..." }, { "Oleg": "все равно по совокупности." }, { "Sergei": "В среднем, да, получается константин." }, { "Oleg": "В среднем она как-то амортизационная, амортизационная." }, { "Sergei": "На амортизацию ходит, поэтому и она не считается. Потому что вероятность такого плохого случая она низкая." }, { "Oleg": "Она низкая, она редко происходит. Вообще вот сама по себе бегу нотаться вот этого. О там, от n, от log n. Вот она как бы ну... Можешь про неё рассказать своими словами, как бы кратко?" }, { "Sergei": "Ну, эта нотация нам говорит о некой алгоритмической сложности, то есть мы её таким образом обозначаем примерно сколько у нас будет выполняться алгоритм по времени, да, если у нас будет там какое-то число n, которая в идеале даст стремиться к большому числу, потому что это всё показательно больших числах. И относительно, как бы там, соответственно, есть два показателя, это временная сложность о атентам и разные зависимости есть, сейчас они я их скажу. И вторая, это у нас, соответственно, Space Complexity, это затраты по памяти, то есть сколько мы памяти еще. Это и тема, либо иным алгоритмом, сколько памяти потребляем. Соответственно, бывают константные, это вот самый идеальный вариант, когда у нас там сложность по времени, либо сложность по затратам памяти, она не зависит от количества элементов, которые она обрабатывает, вот например, там хэштаблицы. У нас есть следующая, это там логерифмическая сложность, это вот пример там дерева. анордрат сет или анордрат мэп то есть когда у нас для того чтобы мы там нашли нужный нам элемент мы общий число n делим при каждой итерации ну по факту попала и соответственно здесь мы выходим на логарифм дальше у нас идет линейная сложность то есть когда нам например у меня посортированном массиве или тренеры не отсортированным, не порядочным, надо найти какой-то нужный нам элемент. Нам, соответственно, в худшем случае надо пройтись весь массив, если у нас там то, что мы ищем, в самом конце находимся. И, соответственно, здесь будет линейная сложность. Дальше идет... Ну, я сейчас начну с квадратной, да, с квадратичной сложности. То есть, n квадрат, то есть, когда у нас, допустим, квадратическая сложность. Ну, допустим, у нас есть n. элементов. Ну, и мы пишем там двойной цикл, который перебирает элементы. С первой цикл, там второй цикл. Вот, соответственно, первый цикл там перебирает с нуля до единиц, там второй цикл, там с нуля до единиц. То есть, допустим, мы перебираем там какие-то их сочетания. Соответственно, мы вылезаем в квадратичную сложность тратическую. А есть то, что посередине находится между линейной и квадратической, это, например, для алгоритмов сортировки. У нас есть сложность n умножить на логорифмат m, то есть это такая, как во ни n квадрат, но и ни n, где-то вот оно, значит, посередине между ними. Ну и есть самое вообще страшное, это самая, вид сложности алгоритмической, это фактериал. Вот есть какие-то специальные класс-задачи, по-моему, задачи комиво-воежёра, которым у нас там объехать, по-моему, все города, сейчас не помню точных контекстов, но, в общем, она до сих пор не решена, но она решается со сложностью n в катериал. Зачем там больше будет городков? пообщем, там все это взлетает буквально. Я не помню, по-моему, факториал 20, по-моему, уже, да, у нас не хватает лонг-лонг, лонг инд, для того, чтобы там почитать количество, ну, разумер, да, по-моему, так... надо посмотреть." }, { "Oleg": "Ну, да, да, да, да, да, да, да, да." }, { "Sergei": "Похоже на правду наверно. Ну да, экспоненциальный еще, да, и бывает. Ну, в общем, да, факториал до жесткой вещи согласят. Подробно. и хорошо там, значит еще на тему сложности, что-то хотел спросить и вылезло из головы." }, { "Oleg": "Да, вот про контейнеры еще, вот у листа, да, стандартного нашего, есть такая функция splice называется, вот это такая достаточно уникальная для листа операции, потому что у других контейнеров ее нет, вот она позволяет врезать один лист в другой, то есть допустим у нас есть лист из там 10 элементов и листом из 3 элементов и мы можем сказать splice вот сюда и он как бы разорвет первую листь и туда вставит все элементы второго листа, вот и это в случае листа возможно сделать за константу, ну потому что у него вот связи эти просто настраиваются, вот иногда спрашивают такой вопрос, к какому компромиссу введения этой функции там приводят в случае листа, вот знаешь так сходу или нет?" }, { "Sergei": "Сергей, смотри, я, во-первых, первый раз в тебя про сплайс услышал, ну, то есть я считал, что там инсерт, да, как бы инсерт в принципе то же самое, да, там делает, то есть нам, но здесь получается, что на самом деле инсерт у нас, да, если мы знаем позицию, в которой надо инсерть, то есть тут у нас, мы можем там перебить эти указатели у нас же, да, хранят указатели, то есть, по сути, перебить указатели и вставить, ну, эти элементы, но дело в том, что для того, чтобы вычислять вот эту позицию, то есть, мест, в которые нам надо вставить, да, Вот здесь у нас как бы линия, то есть сама вставка элемента..." }, { "Oleg": "Нет, нет, когда мы знаем, куда вставлять уже, то есть вот мы говорим сюда, вот сюда, и, значит, указываем это раток, да, и говорим, какой лист туда засплайся-то получается. И вот эта вещь отрабатывает за константов. А компромиссы имеется в виду, что есть еще одна очень как бы нужная функция листа, которая из-за этого, из-за сплайса она... ухудшается ее алгоритмическая сложность, к сожалению." }, { "Sergei": "за сплайс." }, { "Oleg": "Да, то есть у нас компромисс, мы либо сплайс сделаем константным, либо вторую функцию делаем константным. По поводу сплайса, я так понимаю, он работает быстро, да, потому что нам, по сути, надо только взять первый элемент списка, которую мы вставляем, да, и у него указатель перебить на предыдущий и его указатель перебить на следующий, ну, относительно инсерта, то есть, да, здесь констанция, да, у нас получается." }, { "Sergei": "А почему это может мешать?" }, { "Oleg": "А получается, что там на самом деле тот сплайс, ну, тот список, который мы вставили, второй-то получается, элементы помовились, то есть они уже в том списке, ну, неволидные, да, он простое остается, то есть или и тут и там, они дублируются." }, { "Sergei": "Ну, по идее, итераторы должны оставаться валидными, то есть это хороший вопрос, я так сходу не могу ответить даже если честно." }, { "Oleg": "Да, итераторы должны оставаться валидными, указатели должны, ссылки должны, все должны оказаться валидными, как мне кажется. Но можно отдельно посмотреть." }, { "Sergei": "Ну, давай не будем там долго." }, { "Oleg": "Да, почему может это попортить какую-то функцию стальную? Посмотри, тут если у нас как бы вставка, может быть тут вопрос тогда про удаление, то есть обратная какая-то операция." }, { "Sergei": "Ну, не знаю, у меня версии пока больше других нет." }, { "Oleg": "То есть что мы можем попортить? Попортить чисто алгоритмическую сложность. Вот у нас лист, ну, по-хорошему, он, чтобы посчитать количество своих элементов в сайти. он должен пройти по всем элементам, но мы в принципе можем в листе хранить это как константу, но когда мы делаем сплайс, то там неизвестное количество элементов." }, { "Sergei": "Всё понятно, то есть, да, вот какая-то такая ситуация. Ну да, вот я тоже как бы думал, то есть ему на самом деле надо пересчитать размер, то есть указатель это первого и последнего, он переперезовяжет этот констант, а скоб в середине то он не знает, то есть по ходу ему надо это самое проходиться, а как это выстрелить решено?" }, { "Oleg": "А, по-моему, там есть этот самый выбор, там можно с помощью По-моему, там можно, исходно вообще-то в STL было сделано, что сплайс константный, потому что ни одного другого контейнера такого нет, о такой операции. И это как бы такая уникальная фишка листа, что он такой может. Но я видел реализации, в которых это с помощью шаблонного аргумента решается. То есть ты либо сайс константный делаешь, либо сплайс, короче, константный делаешь." }, { "Sergei": "Ну то есть если сайс, да, мы дальше берем, то он его актуализирует, пересчитывает таким, после сплайса, он на него поехал." }, { "Oleg": "Ну да кстати как бы тонкость такая да но иногда вот вылезает такая ерунда так смотри нам еще бы успеть но в принципе да наверное мы сейчас легко это мусор должны сделать значит сейчас с ссылку пришлю на редактор Так, мэйлица ПП, первая точка, а, ну да-да-да, в общем-то, здесь надо написать функцию АТУИ, да, ну вот, которая из ЧР-звездочки СТР нам вернет Инд. Давай исходить сначала из того, что у нас только положительные числа там будут. Ну, а аргумент конс-чарзвёточка. Как стандартная функция есть, а то и?" }, { "Sergei": "Да, да-да-да." }, { "Oleg": "Давай подумаем, что нам тут надо будет. Допустим, у нас там ничего не написано. 123.5.6. Вот так, вот так. Кстати, могут быть еще варианты. Наверное, так, да. Могут еще быть. Вот такой вариант, я не знаю, тут мы будем тогда проходиться до первого." }, { "Sergei": "Да, первой символа." }, { "Oleg": "Так, теперь..." }, { "Sergei": "Можете сейчас плюсик начинаться?" }, { "Oleg": "Да, еще может плюс быть, минус пока не берем, да?" }, { "Sergei": "Да, давай не без минуса пока что." }, { "Oleg": "То есть вот так на самом деле, может еще так?" }, { "Sergei": "Да, ну это здесь будет, да, вот так будет 125, а может быть там плюс и какая-то строка левая, да, просто на входе, в принципе." }, { "Oleg": "Вот тогда 0 вернет. Так, так, так так, так, так, так... Ну по идее тут нам нужно как бы добираться с последнего, да, числа И идти вперед, потому что у нас будет старший разряд Давай подумаем сейчас Как это будет лучше сделать или можно идти вперед, но тогда умножать результат на десятку И цифрку прибавлять Вот если сейчас мы не сильно заморачиваем все оптимизации, можно пойти как бы с начала и умножать просто на десятку Символа." }, { "Sergei": "Символа." }, { "Oleg": "Так, ну тогда здесь сделаем рез какой-нибудь, пока он будет нулю. Ну, то есть пока у нас там..." }, { "Sergei": "Пока у нас, ну, мы не дошли строчку до конца." }, { "Oleg": "Да, сейчас пока напишем вариант, когда у нас там не... Ну, хорошая строка, да, мы ее до конца как бы добили, она дала нам там результатик, и дальше там посмотрим. Тут, соответственно, вернем какой-то результат. Теперь, что мы здесь делаем? Нам надо соответствовать на char. Сега у нас, сейчас, while s, сейчас это у нас указатель. Это у нас указатель на строку. На строку, соответственно, сейчас я пытаюсь вспомнить. Там пока... Давай, пока так, теперь, соответственно, мы извлекли первый, первый символ, и, условно говоря, ушли, ушли там дальше, куда-то. Типхеречия здесь. Мы что с ним делаем? Мы должны посмотреть, посмотреть, ну, то есть, нас удовлетворяют символы. Символ плюс нас удовлетворяет и нас удовлетворяет символ от 0 до 9. Тогда сейчас некая эволюдация. ну пока основной да основная это самая наша соответственно что мы здесь будем тогда тогда мы циферку преобразуем в число это у нас будет ци минус ну нулик то есть чтобы понять что за чиселка там вот теперь мы должны будем рез умножить на 10 мы должны вот и прибавить эту эту циферку Так, соответственно, вот здесь, наверное, мы просто там прервемся, сделаем брейк, то есть, если мы дошли там до какого-то значения, и оно у нас не число, ну, тогда мы просто отсюда вылезем. Вот, теперь нам надо плющик обработать." }, { "Sergei": "то есть плюсик мы соответственно будем обрабатывать только если у нас это как бы да начало начало должны мы должны его вот давай сделаем старт старт Будем проанализировать ток-о-тока на старте после чего у нас старте станет фэлс. Теперь на старте, на старте, на старте. Ну точнее вот так на старте и сейчас поправлю. Так, если у нас ц равняется..." }, { "Oleg": "Плюс тогда мы Сделаем старт-фэлс и континюю. Теперь если у нас не старт и у нас там попался плюс, то тогда мы, а давай тогда мы не так напишем. То есть мы отдельно проанализируем плюс. И здесь внутри мы посмотрим IfStart, тогда мы сделаем Вот. Так, это мы уберем, так. Ну, здесь сейчас кажется, что, может быть, да." }, { "Sergei": "А, ну, окей, в Таиллс есть. Давай, да, смотрю." }, { "Oleg": "Да, ну, то есть, если мы попали на плюс, то есть, если мы в самом начале, в самом начале, то тогда мы, соответственно, переходим к следующему, поснимаем флажок, продолжаем. Так, иначе мы, ну, я думаю, что здесь, в данном случае, сделаем брейк, то есть, по сути, ну, как бы, вернем там ноль. А этот L с относится у нас к IFF, у которой, я что-то сейчас потерялся, IFF, так, скобка открылась, так, IFF." }, { "Sergei": "А, то есть этот L с относится к IFF, у которой старт." }, { "Oleg": "сейчас вот этот на 22 строчки а сейчас сейчас сейчас сейчас да Yeah Так, если старт, то есть если у нас плюсик, если мы в самом начале, то как бы пометили, пошли дальше. Иначе, ну, считаем, что вот здесь у нас, да, вот какая-то такая ситуация, либо, допустим, вот такая ситуация, да, тогда вот здесь вот у нас должна будем прерваться, ну, как-то, да, вот здесь галочку поставим. вот здесь мы прервемся так сейчас давай я хочу это самое вспомнить так вилл сейчас меня что-то вот это сейчас указатель давно с этим сейчас сейчас звездочек когда не работал вот это вилл с вилл с это по сути указатель" }, { "Sergei": "Да нет, всё верно?" }, { "Oleg": "Наверное, нет. Всё, всё." }, { "Sergei": "Там же мог быть NAL? Я может передаваться NAL?" }, { "Oleg": "Да, да, да." }, { "Sergei": "Да. Так, ну что, тогда это самое какое-нибудь прогоним, да?" }, { "Oleg": "Не, ну, сейчас будет проблема, если у тебя будет, допустим, 5 плюс 2 написано. Вот что у тебя будет в этом случае?" }, { "Sergei": "5 плюс 2. Давай смотреть. Значит результат. Погнали. Сейчас результат. Мы здесь напишем. Start. Нам надо еще Start куда-то откнуть. Прошли. старт, континую, давай да получается так что смотри здесь получается что мы если у нас тогда это написано то мы вот этот блок пропускаем дальше у нас врез словно говоря записывается пятерка пятерка вот дальше у нас попадает плюсик ну давай здесь еще наш ц выведем Пятерка, старт у нас фэлс, друг точнее. Получается, что пятерка, потом у нас туда попал плюсик. Вот эта штука стала фэлсом, но мы ушли на следующую тюрацию, то есть у нас сюда двойка попала. То есть нам нужно, соответственно, вот здесь сделать старт. Тогда мы вот здесь вот перешли, когда пятерочку обработали, у нас стал-стал-стал. Мы вот этот блокчок уже больше не поделали. Не вернем пятерку, просто получается, да." }, { "Oleg": "Да, получается, что вернем пятерочку." }, { "Sergei": "Есть еще одна проблема, похожа с переполнением возможным." }, { "Oleg": "Так, так, так." }, { "Sergei": "А если у нас очень большое, да, число, то есть какое-то вот супер, там, огромное там." }, { "Oleg": "Ну да, 3 миллиард, допустим." }, { "Sergei": "Но при переполнении она, по идее, должна ноль возвращать, насколько я помню, а то и... При переполнении ноль. Так, сейчас тогда, соответственно..." }, { "Oleg": "Так как нам отследить переполнение, у нас есть intmax, да, такое значение. Это получается 2 в степени, 2, 31. Так, но, сейчас, по кулькулятору, посмотрим. Так, два, три, четыре, четыре, четыре, четыре, четыре," }, { "Sergei": "По-моему, вот так с минус единичкой, да." }, { "Oleg": "Соответственно, нам надо следить. Нам надо следить. То есть, чтобы у нас рез был." }, { "Sergei": "То есть, если у нас результат." }, { "Oleg": "То есть, если у нас результат." }, { "Sergei": "Uh" }, { "Oleg": "Так, и следующее число. То есть, если у нас результат. Так, и следующее число нас может удовлетворить только от 0 до 7, получается, да? То есть, если оно там, допустим, уже 8 или 9, то вот здесь вот у нас должна быть, ну, как бы... Ты говоришь, мы должны ноль, да, вернуть, если передолнение? Так." }, { "Sergei": "Ну, либо если у нас рез текущий больше этого числа, и есть еще цифры, да, после этого." }, { "Oleg": "А, да, давай сформулируем это условие, то есть если рез больше Больше вот этого числа и это уже достаточно кстати потому что мы и так уже в цикле то есть если рез больше можем уже сразу 0 возвращать правильно мы же уже в цикле обрабатываем следующую цифру" }, { "Sergei": "Да, но если она от нуля до семьи, то нас это устроит." }, { "Oleg": "Не, а рез-то больше? А, все, рез больше, то есть получается, сейчас, а, он будет вот здесь пятерка. Все, я тебя понял. То есть получается вот здесь, допустим, ну, на что он больше? Вот так, да? Это нас уже не устроит. Сейчас а мы, а, все, да, да, да, да." }, { "Sergei": "то есть получается вот этого достаточно но это одно условие есть еще второе условие он может быть равен этому числу но тогда да должен быть как-то сказал так если результат больше тогда вот здесь третерн сделаем ага так есть соответственно второе условие сейчас мы его тоже пропишем то есть если он равен вот этому числу И вот эта наша чарка, она 0-1, да, посмотрим, 0, точнее 8, либо 9, ну тогда мы тоже, да, ретурм делаем." }, { "Oleg": "Да-да, ну, по сути, да, если больше она 7, то ретурм надо. Ну, давай тогда вступим, сейчас." }, { "Sergei": "Да, нет, давай уже не будем сейчас это дописывать, в принципе, да, у нас уже время кончается, я хотел еще момент обсудить один." }, { "Oleg": "Ну, все, в принципе, окей. Допиши ее, просто сам потом. Может быть, упростишь немножко. Вот, напиши тест, чтобы прогнать. Вообще, эта функция в начале еще пропускает пробелы и какие-то табуляции. Можно ее улучшить таким образом." }, { "Sergei": "Я помечу. Потом вспомню задачу слиткода, а то и там. По-моему, есть такая, я даже сейчас..." }, { "Oleg": "Возможно, возможно. Наверняка. Так, ага, пробелы пропускаем." }, { "Sergei": "Да, второй момент. Это, если бы мы работали с отрицательными числами, помнишь что-нибудь про переполнение отрицательных чисел?" }, { "Oleg": "Ну сразу скажу, они там в эти, а они в положительные превращаются." }, { "Sergei": "Нет, это undefinedBehavior. Вот переполнение отрицательного инта, это undefinedBehavior. То есть положительные мы можем, да, переполнять. Да, это надо как бы аккуратно отслеживать. ну просто такой вопрос может там возникнуть вот и да хорошо бы его не забыть" }, { "Oleg": "ну а так в принципе все мы по всем вопросам прошлись вот мне кажется что у тебя готовность высокая там интервью еще будет это понем второй этап там какие-то будет еще возможно не я буду проводить на вероятно там про виртуальность всякое такое там будет про это будет еще ну тоже как бы дать технический прогон чтобы мы это прогнали" }, { "Sergei": "Там какие-то проект конструктора деструктора наверное про исключение вот вопросы." }, { "Oleg": "Так, из конструкторов-деструкторов, в том числе, NoExcept." }, { "Sergei": "Так, шаблоны, какие-то вопросы по шаблонам. Потом такие вещи, как вот есть сфиная такая, знаешь, что-то сфиная такая, как идиома." }, { "Oleg": "Да-да-да." }, { "Sergei": "Ну так, просто, ну как, вы это всё пройдёте, в принципе, то есть это напомнят тебя про это." }, { "Oleg": "Могут просто." }, { "Sergei": "Ну, если хочешь, ты можешь вот почитать про солид, что-нибудь могут спросить, про пимпл. И, может, еще какие-то будут задачки, я не знаю, если успеется это все, тут как бы такое условное разделение на такие секции, то есть вроде какие-то больше, какие-то меньше, смотря на сколько глубоко там уходить. Ну, в целом, как бы, мне кажется, у тебя хорошая готовность, так что не должно быть сложно." }, { "Oleg": "А по шаблонам, что там обычно спрашивают?" }, { "Sergei": "Да, сейчас посмотрю, вот у меня есть тут список передо мной есть по шаблонам, по шаблонам, так." }, { "Oleg": "Я давно вот, по-второй части, я вообще, обычно интервью провожу именно, поэтому я уже подзабыл немного какие-то вопросы. Давно последний раз был прогон, особенно по второй части, вот по-первой." }, { "Sergei": "Так, сейчас. Шаблон, где же она тут? Видел только что. а ну вот прочистичные специализации там шаблонных классов ну понятно там функции да что нельзя так шаблон указываем параметрами две частичные специализации вот прочистичная специализацию судя по всем может быть вопрос но без конкретики какой-то вот здесь то есть это на на усмотрение." }, { "Oleg": "Понял, хорошо." }, { "Sergei": "Ну, хорошо, отлично, надеюсь было полезно, вот так что..." }, { "Oleg": "Ой, ты знаешь, очень спасибо огромное, на самом деле, ты знаешь, так классная вещь, иногда вот эти вот интервью, вот. Ну и вообще, ты знаешь, как с обеседником, ну, приятно какие-то общие вопросы, темы, ну и себя там проверить, да, немного." }, { "Sergei": "Сто процентов, очень классно, ну я рад." }, { "Oleg": "Я просто очень доволен, и спасибо тебе огромное, на самом деле." }, { "Sergei": "Спасибо, приятно всегда слышать позитивные фидбаки тоже. Хорошо, удачи тогда, я напишу там сегодня свои какие-то моменты, то что мы обсуждали. Отмечу там то, что просят. Ну и там уже планируете следующий этап. Вот, удачи." }, { "Oleg": "Спасибо, удачи." }, { "Sergei": "Давай, пока." }, { "Oleg": "Ah Thank you. Thank you. Thank you very much. Thank you. Thank you." }\]