В референсной реализации, как я понял, - хранит указатель на контрольный блок с виртуальными функциями clone, destroy и виртуальным деструктором. Присваивание с мувом приводит к перекидыванию указателя (при условии, что аллокаторы одинаковы)
Кстати, вопреки распространенному мнению, конкретно ложные лисички (ака оранжевые говорушки) не ядовиты, некоторые их даже намеренно собирают. Та же фигня с большинством ложных опят, да и легендарный "ложный подберезовик" на поверку оказывается невкусным, но совершенно безопасным грибом.
Что, разумеется, не отменяет существование действительно очень опасных грибов, которые иногда даже опытные грибники умудряются путать со съедобными.
Похоже, что именно соображения безопасности привели к выбору для заготовок довольно характерных грибов - белые, маслята, млечники (вроде груздей и рыжиков), лисички. Эти ребята - бро, спутать их с чем-то опасным практически невозможно (тем не менее, принцип "не знаешь - не бери" надо соблюдать всегда)
Cтандартный аллокатор неизбежно сделает что-то вроде:
установит мьютекc или применит любой другой доступный способ синхронизации
обратится к ОС за памятью
ОС выполнит довольно заковыристый алгоритм для поддержания структуры данных heap'а.
Полагаю, на практике разработчики стандартной библиотеки могут в целях оптимизации не всегда бегать за памятью к системе, а поддерживать собственные кеши - тогда часть работы перемещается на библиотеку, системный вызов осуществляется время от времени. Но поддержка потокобезопасности и общее назначение алгоритма аллокации все равно выходят дорого, по сравнению с потенциальной пользой от специализированной стратегии аллокации.
По сравнению с этим, вызов виртуальной функции (всего-то два перехода по указателю) - просто капля в море. Современные компиляторы этот вызов еще и зачастую девиртуализировать могут.
в общем случае интерфейс сstd::vector, конечно, малость оверхед(будет хорошо работать только при условии, что временные объекты не создаются), правильная альтернатива - std::span (если нам позарез нужен указатель на массив в памяти, например, для передачи в C API), ну и пара итераторов/диапазон для работы с "конвенционными" контейнерами C++
Концептуально, причина возникновения рака всегда одна - неудачные сбои копирования генома клеток. Ошибки в копировании случаются и без внешних причин, и в общем-то это - норма и движущая сила эволюции. Проблема в том, что злокачественная опухоль - это и есть результат эволюции, эволюции линии клеток, вырвавшихся из-под контроля организма. Известны даже случаи, когда подобные линии клеток переживали хозяев, фактически становясь самостоятельными биологическими видами, ака "трансмиссивная злокачественная опухоль"
Во всех нас, даже трижды здоровых людях, живущих в идеальных экологических условиях, постоянно возникают клетки с потенциально опасными мутациями. Для того, чтобы заболеть, всегда нужно очень неудачное стечение обстоятельств: каскад приспособлений для независимости, и игнор со стороны имунной системы.
Хотя вредные факторы вроде химических мутагенов или ионизирующего излучения могут многократно увеличить риск, это всегда результат случайного процесса.
Пошел он в народ, пошел. Если говорить о личном опыте - то у нас в 2010ых все знакомые именно 3.58 гоняли и друг другу копировали, мне тоже именно ее посоветовали.
Но WOG уж очень забагованный был, вылет на ровном месте во время твоего, или, что еще хуже, хода ИИ - обычное дело. Когда появилась Хота, органично и сбалансированно расширяющая игру и развивающаяся совместно с HD модом - она быстро стала доминировать
В Skype точно было. Причем оно умудрялось распознавать два разных случая - когда тыкают рандомные клавиши, собеседник видел ломающийся карандаш, а при зажатии нескольких - собственно котэ
Компилятор перехитрил сам себя. Итак, что происходит?
Тут-то UB происходит: нельзя читать из неинициализированной переменной. Поскольку недопущение таких вещей в зоне ответственности программиста - компилятор справедливо считает что на входе будет bool с конвенционным значением, и оптимизирует как умеет.
Кстати, кто-нибудь знает, может ли сгенерироваться подобный код функции, если компилятор увидит вместо неинициализированной переменной какое-нибудь memcpy(&x, src, sizeof(x))?
Оу, извините, все равно непонятно, почему же получается проще прикрутить к телефону второй модем, а не добраться до встроенного :'(
Правильно ли я понимаю, что по сути проблема в том, что для всей звуковой системы телефона просто нужны заковыристые драйвера, которые по-быстрому не написать и в опенсорсе не доступны, или есть какие-то более фундаментальные трудности?
Извиняюсь, если вопросы глупые, я во внутренностях линухов (и особенно телефонов на нем) не силен, но тема чертовски интересная!
Это и для реальных экранов нормально, ведь экран загрузки обычно показывает прогресс по некоей конкретной, заданной разработчиками, очереди задач, а после ее окончания может проделываться еще какая-то тяжелая работа в главном потоке, из-за которого собственно все и подвисает.
Но, в отличие от поддельного, тут есть два преимущества: время подвисания более-менее фиксированное и зависит обычно только от производительности девайса, а еще это можно зарефакторить и таки сделать по-человечески =)
Довродилось ковыряться в системе загрузочных задач движка одной мобильной игры, так вот у нас все было относительно честно: общий прогресс определяется количеством запланированных и завершенных задач, а так же локальным прогрессом самих задач. Те таски, которые могли (и хотели) точно сообщать о своих достижениях, сообщали, некоторые мухлевали и выдавали приблизительный результат, некоторые о прогрессе не сообщали и результат бинаризовался.
Но вот в разделе про move - семантику, кмк, упустили самое важное - суть этого нововведения, ограничившись какими-то волшебными примерами "перемещения".
А суть в общем-то проста - это именно семантика, позволяющая писать разный код для работы со временными и "долговременными" объектами, rvalue и lvalue. Именно благодаря знанию о сущности аргумента оператора присваивания или конструктора можно написать гораздо более эффективный код, в случае того же std::vector'а позволяющий просто(* за редкими исключениями наподобие несовместимых аллокаторов) обменять указатели на реальный массив вместо честного поэлементного копирования.
ЕМНИП, в опенсорсных реализациях диспетчеризация действительно реализована без виртуальных функций, но она там такая же динамическая, просто написанная вручную.
А вот в оказавшийся под рукой STL из MSVC я даже заглянул: внутри создается объект, реализующий интерфейс _Func_base, то есть в общем-то ровно как у Вас, только чуть более заковыристо и универсально и со Small buffer optimization.
А еще для повышения привилегий есть отличная утилита командной строки - gsudo . Теперь можно запускать от имени админа только то, что действительно этого требует :)
Ну, кроме сложностей с изучением самих шаблонов у новичков (да и у старичков тоже, будем честны) возникают трудности с чтением простыней ошибок инстанциирования шаблонов. По идее, при широком распространении концептов ошибки станут гораздо понятнее, что тоже должно понизить порог входа...
В референсной реализации, как я понял, - хранит указатель на контрольный блок с виртуальными функциями clone, destroy и виртуальным деструктором. Присваивание с мувом приводит к перекидыванию указателя (при условии, что аллокаторы одинаковы)
Там еще довольно много отличий, вытекающих как раз из специфики типов-значений, вот что сходу вспомнилось:
распространение константности на хранимый объект
поддержка аллокаторов
автоматическое оборачивание операторов сравнения (бинарных и
operator<=>
) иstd::hash
ну и да, автоматическое копирование и перемещение значения (в случае с
std::polymorphic
это еще и изящно решает проблему клонирования)Есть референсная реализация, которую можно использовать уже сейчас
Кстати, вопреки распространенному мнению, конкретно ложные лисички (ака оранжевые говорушки) не ядовиты, некоторые их даже намеренно собирают. Та же фигня с большинством ложных опят, да и легендарный "ложный подберезовик" на поверку оказывается невкусным, но совершенно безопасным грибом.
Что, разумеется, не отменяет существование действительно очень опасных грибов, которые иногда даже опытные грибники умудряются путать со съедобными.
Похоже, что именно соображения безопасности привели к выбору для заготовок довольно характерных грибов - белые, маслята, млечники (вроде груздей и рыжиков), лисички. Эти ребята - бро, спутать их с чем-то опасным практически невозможно (тем не менее, принцип "не знаешь - не бери" надо соблюдать всегда)
Cтандартный аллокатор неизбежно сделает что-то вроде:
установит мьютекc или применит любой другой доступный способ синхронизации
обратится к ОС за памятью
ОС выполнит довольно заковыристый алгоритм для поддержания структуры данных heap'а.
Полагаю, на практике разработчики стандартной библиотеки могут в целях оптимизации не всегда бегать за памятью к системе, а поддерживать собственные кеши - тогда часть работы перемещается на библиотеку, системный вызов осуществляется время от времени. Но поддержка потокобезопасности и общее назначение алгоритма аллокации все равно выходят дорого, по сравнению с потенциальной пользой от специализированной стратегии аллокации.
По сравнению с этим, вызов виртуальной функции (всего-то два перехода по указателю) - просто капля в море. Современные компиляторы этот вызов еще и зачастую девиртуализировать могут.
в общем случае интерфейс с
std::vector
, конечно, малость оверхед(будет хорошо работать только при условии, что временные объекты не создаются), правильная альтернатива -std::span
(если нам позарез нужен указатель на массив в памяти, например, для передачи в C API), ну и пара итераторов/диапазон для работы с "конвенционными" контейнерами C++Концептуально, причина возникновения рака всегда одна - неудачные сбои копирования генома клеток.
Ошибки в копировании случаются и без внешних причин, и в общем-то это - норма и движущая сила эволюции. Проблема в том, что злокачественная опухоль - это и есть результат эволюции, эволюции линии клеток, вырвавшихся из-под контроля организма. Известны даже случаи, когда подобные линии клеток переживали хозяев, фактически становясь самостоятельными биологическими видами, ака "трансмиссивная злокачественная опухоль"
Во всех нас, даже трижды здоровых людях, живущих в идеальных экологических условиях, постоянно возникают клетки с потенциально опасными мутациями. Для того, чтобы заболеть, всегда нужно очень неудачное стечение обстоятельств: каскад приспособлений для независимости, и игнор со стороны имунной системы.
Хотя вредные факторы вроде химических мутагенов или ионизирующего излучения могут многократно увеличить риск, это всегда результат случайного процесса.
Спасибо за комментарий, намеренно искал, написал ли кто-то уже об этом.
И кмк это ведь как раз одно из важнейших нововведений C++14, оказавшее огромное влияние на написание кода.
Здорово, конечно, но давно же существует gsudo, которая делает все то, что обещают Майкрософтовцы.
Авторам оригинальной тулзы, наверное, щас обидно было...
Пошел он в народ, пошел. Если говорить о личном опыте - то у нас в 2010ых все знакомые именно 3.58 гоняли и друг другу копировали, мне тоже именно ее посоветовали.
Но WOG уж очень забагованный был, вылет на ровном месте во время твоего, или, что еще хуже, хода ИИ - обычное дело. Когда появилась Хота, органично и сбалансированно расширяющая игру и развивающаяся совместно с HD модом - она быстро стала доминировать
а лично мне Виста понравилась сразу с момента выхода, даже больше чем 7
В Skype точно было. Причем оно умудрялось распознавать два разных случая - когда тыкают рандомные клавиши, собеседник видел ломающийся карандаш, а при зажатии нескольких - собственно котэ
Вот, например, FAQ из хорошего канала в Telegram:
https://github.com/JoshuaJakowlew/cppfaq
Тут-то UB происходит: нельзя читать из неинициализированной переменной. Поскольку недопущение таких вещей в зоне ответственности программиста - компилятор справедливо считает что на входе будет bool с конвенционным значением, и оптимизирует как умеет.
Кстати, кто-нибудь знает, может ли сгенерироваться подобный код функции, если компилятор увидит вместо неинициализированной переменной какое-нибудь
memcpy(&x, src, sizeof(x))
?Оу, извините, все равно непонятно, почему же получается проще прикрутить к телефону второй модем, а не добраться до встроенного :'(
Правильно ли я понимаю, что по сути проблема в том, что для всей звуковой системы телефона просто нужны заковыристые драйвера, которые по-быстрому не написать и в опенсорсе не доступны, или есть какие-то более фундаментальные трудности?
Извиняюсь, если вопросы глупые, я во внутренностях линухов (и особенно телефонов на нем) не силен, но тема чертовски интересная!
Это и для реальных экранов нормально, ведь экран загрузки обычно показывает прогресс по некоей конкретной, заданной разработчиками, очереди задач, а после ее окончания может проделываться еще какая-то тяжелая работа в главном потоке, из-за которого собственно все и подвисает.
Но, в отличие от поддельного, тут есть два преимущества: время подвисания более-менее фиксированное и зависит обычно только от производительности девайса, а еще это можно зарефакторить и таки сделать по-человечески =)
Довродилось ковыряться в системе загрузочных задач движка одной мобильной игры, так вот у нас все было относительно честно: общий прогресс определяется количеством запланированных и завершенных задач, а так же локальным прогрессом самих задач. Те таски, которые могли (и хотели) точно сообщать о своих достижениях, сообщали, некоторые мухлевали и выдавали приблизительный результат, некоторые о прогрессе не сообщали и результат бинаризовался.
Спасибо за статью!
Больше C++, хорошего и разного.
Но вот в разделе про move - семантику, кмк, упустили самое важное - суть этого нововведения, ограничившись какими-то волшебными примерами "перемещения".
А суть в общем-то проста - это именно семантика, позволяющая писать разный код для работы со временными и "долговременными" объектами, rvalue и lvalue. Именно благодаря знанию о сущности аргумента оператора присваивания или конструктора можно написать гораздо более эффективный код, в случае того же
std::vector
'а позволяющий просто(* за редкими исключениями наподобие несовместимых аллокаторов) обменять указатели на реальный массив вместо честного поэлементного копирования.Все примерно так и есть.
ЕМНИП, в опенсорсных реализациях диспетчеризация действительно реализована без виртуальных функций, но она там такая же динамическая, просто написанная вручную.
А вот в оказавшийся под рукой STL из MSVC я даже заглянул: внутри создается объект, реализующий интерфейс _Func_base, то есть в общем-то ровно как у Вас, только чуть более заковыристо и универсально и со Small buffer optimization.
А еще для повышения привилегий есть отличная утилита командной строки - gsudo . Теперь можно запускать от имени админа только то, что действительно этого требует :)
Ну, кроме сложностей с изучением самих шаблонов у новичков (да и у старичков тоже, будем честны) возникают трудности с чтением простыней ошибок инстанциирования шаблонов. По идее, при широком распространении концептов ошибки станут гораздо понятнее, что тоже должно понизить порог входа...