Интересный курс. Задорное начало. Велосипеды строк мне напомнили про Stroka и Wtroka от Yandex. Собственно, все крупные компании грешат велосипедами, когда всё своё. Я понимаю, что поздновато комментировать, но format библиотека -- это не инициатива Microsoft, а внесённая в стандарт fmtlib Виктора Зверовича (P0645R10). Сейчас он, кажется, работает в Meta. Формат строковую интерполяции там взят, скорее, из Python форматирования. Такой вариант удобен, когда надо, например, повторно использовать аргументы. `{0} {1} {0}`. В таком духе. Плюс, конечно большой от неё в том, что часть работы происходит во время компиляции. Не очень понятно, зачем автор решил её внести в стандарт, потому что эта библиотека сильно развивается на данном этапе. Её всегда можно использовать header-only или прилинковать статически , подтянув CMake-ом, например, или conan\vcpkg.
1:11:26 Если совсем к слайдам придираться, после параметра Traits забыта запятая, аналогично в презентации для бакалавров (16-containers, 26 слайд, и еще там забыты ; после объявления классов, как и на 24 слайде)
Спасибо за лекцию. Про std::format вынужден не согласиться. Есть fmtlib - чудовищно популярная библиотека, которая легла в основу std::format. И все, кто хочет std::format(например, я) пока пользуются ей. Ну и синтаксис у неё великолепен, в отличии от натыкивания модификаторов и обрубков строк в стрим в fmt::format задаётся единая форматная строка, из которой наглядно видно, как будет выглядеть результат, проверяет типизацию в компайл-тайме и выводит результат прилично быстрее stringstream'а. В общем почему не добавляют std::format в стандартные библиотеки не знаю, но пока есть fmtlib - это не очень большая проблема.
Я за много лет ничего не слышал про эту чудовищно популярную библиотеку и не видел её применений. Видимо она популярна где-то за пределами моего мира, и в общем меня это устраивает. Ввод и вывод в C++ это iostreams.
@@ИнтернетСпасётМир В первую очередь из-за кастомных форматтеров для объектов и полноценной проверки соответствия аргументов, а не на уровне костыля для компилятора. Ну и он полноценно интегрирован в C++, а так же есть вывод {}, когда он сам определяет, как выводить.
@@tilir посмотрела в релизноутах 15-ой версии- таки есть, но экспериментальное. > P0645: The paper is implemented but still marked as an incomplete feature (the feature-test macro is not set and the libary is only available when built with -fexperimental-library). Not yet implemented LWG-issues will cause API and ABI breakage. ну, значит уже вот-вот... (и если добавить по вашей ссылке в аргументы -fexperimental-library - собирается)
Кажется легче было показать auto* x = &"hello world"; auto* y = &5; Казалось бы везде литералы, но почему то первое валидно .а второе нет, заставляет сразу внезапно осознать в чем разница между стринговым литералом и обычным, ну типа... Поинтер на нечто не выделенное в куче, но почему то это валидный код и он не провис Без стандарта пожалуй отвечу на вопрос про nullptr Для создания значения поинтера не нужно чтение значения nullptr, это работает по принципу тег-диспатчинга. Более того, чтобы создать копию значения nullptr тоже не нужно чтение значения из копии, так что кланг прав. Более того, сама по себе возможность существования volatile int сомнительна, т.к. смысл имеют ссылки и указатели на volatile, а локальная переменная такого типа явно не может быть изменена никак кроме как с помощью УБ
"Для создания значения поинтера не нужно чтение значения nullptr, это работает по принципу тег-диспатчинга." Мне видится так, что это как раз не имеет значения, да вообщем то оба компилятора и явно читают значение. Да и нет никаких гарантий что такое nullptr. А вот эта часть "локальная переменная такого типа явно не может быть изменена никак кроме как с помощью УБ" вроде как похожа на правду, а раз так то и "сайд эфектов" быть не может - следовательно можно вообще volatile удалить с нее (но этого ни один компилятор не делает).
1:07:12 Константин, вроде никто еще не писал, но строчка с enum странная. 1) в конце инициализатора стоит ; что приводит к СЕ 2) у меня в godbolt gcc-12.2 x86-64 даёт SZ равный 1, то есть второй вариативный член union суть массив из одного CharT 3) еще драфт стандарта говорит, что внутри анонимного union "Each member-declaration in the member-specification of an anonymous union shall either define one or more public non-static data members or be a static_assert-declaration. Nested types, anonymous unions, and functions shall not be declared within an anonymous union.", но ни один из основных компиляторов не выполняет это требование (???)
Да, совершенно верно, она странная. На самом деле, там должно быть выражение которое евалуируется в 8, например, вот: enum { SZ = 15 / sizeof(CharT) }; В некоторых источниках сказано что так оно реализовано в GCC. В clang - немного иначе и более компактно. Могу поделиться источниками.
Отличная лекция. Про список литературы: Жаль что доклад про строку Фейсбука такой старый У вас, Константин, ещё где-то была ссылка на видео, где докладчик пытался создать конструктор из двух строк.
22:40 -- я не пойму, почему тут cmut и cinv может лежать в одной и той же памяти? -- если первое неконстантное, а второе константное -- тогда по сути компилятор бы делал возможным изменение константных значений без каста, -- что несомненно нарушало бы здравомысленную логикую
По одному или по разным адресам могут лежать литералы, которыми cmut и cinv инициализированы. Но конечно т.к. инициализация cmut это копирование, он сам будет по другому адресу чем литерал.
@@tilir Некоторые компиляторы которые "поддерживают C++20" по факту поддерживают не все фичи C++20. То ли дело stringstream который изначально с C++11...
А вот что интересно const char* это указатель на память, но на какую память? То-есть где хранится строковый литерал, в какой области памяти. Явно же не в стеке и не в куче. В интернете я вычитал про сегметы в основном играет роль сегмент данных. И я в последнее время отношу строковый литерал именно туда, но так ли это.
на счет std::format -- есть же отдельная открытая реализация на гитхабе. Почему бы ее не внести в stl для gcc? У меня снова флешбеки из прошлого, когда многие реализации почему то юзаются программистами не из stl...
Здравствуйте, Константин. Благодарю за лекцию, как всегда полезная и интересная. Вопрос про последовательность изложения материала. Смотрю эту лекцию после вашего базового курса по С++. И вы рассказываете аудитории про type traits, и сами же говорите, что не все знают, что это, хотя курс называется магистерским. Как так получается, что аудитория на магистерском курсе не знает, что вы рассказывали на базовом? Это как то связано с организацией учебного процесса в ВУЗе? UPD: *про специализацию шаблонов рассказываете
ua-cam.com/video/9N_wJ7oIHDk/v-deo.html - так и нет появилось в комментах ответа. Верно ли что прав clang, т.к. по стандарту присваивание b=a должно присвоить значение типа nullptr_t, т.е. nullptr, а в volatile переменной может оказаться все что угодно, но проблема с gcc - это только лишняя операция копирования из ячейки?
ребят такой вопрос (а если читает и автор, Константин, то и ему тоже): как новичку в c++, можно ли начать с этого курса или у Константина есть какой-то курс более вводный, так сказать. Просто немного путаюсь в плейлистах и роликах ютуба: "а точно ли это первый ролик", "а точно ли курс с нуля" и т.д, заранее спасибо.
В закреплённом посте на моём тг-канале приведены ссылки на три основных плейлиста: базовый по C, базовый по C++ и продвинутый по C++. Вот с них и начните. Если C уже знаете, пропускаете тот который по C. t.me/cpp_lects_rus
P.S. cow всегда мне казалось крайне тупой затеей, ну правда, я что сам не знаю нужно мне писать туда или читать? Это очень легко контролируется мной и оно должно контролироваться, чтобы в коде показывать что я делаю Итого берёшь и используешь string_view когда надо читать/ string когда нужно писать(или нужен объект строки сам в функции), собственно всё. А cow это что то на уровне питона, когда можно передавать только "значения" а внутри язык сам решит что тебе лучше p.s. и перфоманс видимо выигрывается только относительно состояния когда мы всегда копируем и нет sso
Не будьте слишком радикальны. Идея COW-строк ничем не хуже идеи shared pointers. И в том и в другом случае мы платим некоторой сложностью. Но мы платим за дело: за возможность не думать где у нас ссылочная семантика, а где семантика значений. Очень часто это большое облегчение, если вам есть о чём ещё подумать в вашей программе.
большое спасибо за ваши труды! очень люблю ваши лекции! надеюсь, вы всё-таки решите продолжать выкладывать свежий магистерский курс - уж очень хотелось бы послушать обновлённые лекции по концептам, range'ам, сопрограммам и прочим радостям двадцатого года. прошлые лекции ведь писались по "горячим следам" тогда ещё грядущего стандарта
Увы, но это плохая идея. Всё дело в том, что std::cout очень просто устроен: это объект класса с перегруженным оператором. А вот std::print устроен настолько сложно, что даже для многих опытных разработчиков объяснить его детали проблематично. Поэтому доя hello world он не подходит т.к. развивает магическое мышление, а у нас тут не пвйтон.
Подскажите пожалуйста, когда во второй части сказали "скачать стандарт" - это что именно имелось в виду? Нагуглить удалось что есть стандарты либо платные либо драфтовые - это верно? Помогите со ссылкой!
Главный аргумент это не многопоточная среда. Даже в однопоточной среде главный аргумент это инвалидация указателей. Я если что тоже за COW строки в стандарте как политику для строк.
@@giorgi_pa только для COW строк. Представьте что у вас есть две строки: S1 и S2 и они делят буфер A. Вы говорите S1[5]='a'. В этот момент для неё нужен отдельный буфер и теперь S2 владеет A, а для S1 выделился, скажем, B. В другом месте, то есть с другими адресами внутри.
Reading an object designated by a volatile glvalue ... are all side effects which are changes in the state of the execution environment. ... 6.8.1? GCC прав?
@@tilir примерно 15:30. Я после даунтайма ещё не практиковался, а тут ваши лекции удачно попались :) 6.9.1, там 7 Reading an object designated by a volatile glvalue (7.2.1), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects. When a call to a library I/O function returns or an access through a volatile glvalue is evaluated the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile access may not have completed yet. Хотя забавно, в clang 8.0.1 асм такой же, как и в gcc, а в 9.0.0 уже как в примере. Вроде как, если я правильно нашёл, любое действие с volatile должно делать сайд-эффект.
@@tilir Тогда предположу observable behavior. Можно соптимизировать, ничего не изменится. Но тогда никто не неправ. Стандартом это нормально не регламентируется (и не должно) и implementation defined. Сдаюсь короче :)
кстати -- на счет инициализации статических данных -- не нашел нигде в стандарте с++20 (и в с++17) сведений о том, что статические поля инициализируются исключительно строго до функции main(). В стандарте указано, что статические данные инициилизируются до инициализации неглобальных данных и освобождаются строго после них. Никакой привязки именно к функции main() нет.
На самом деле если не лезть в бутылку, то стандарт примерно это и говорит. [basic.start.dynamic] It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized. То есть вроде как откладывать можно, но не дальше, чем использование любой не-инлайн функции или переменной в том же модуле. Ясно, что это исключение сделано только и исключительно для shared object, где действительно при подгрузке модуля переменные инициализируются после main где-то при dlopen. Так что думать об инициализации как о чём-то происходящем "до main" -- в целом вполне правильно с понятными оговорками.
Большое спасибо за то, что даёте возможность абсолютно каждому человеку учиться по нереально крутым и качественным материалам от Вас!
Спасибо за ваши труды!
Доброго дня, спасибо за ваши труды
Классно! Мне очень нравится то, как вы со всех сторон анализируете разные подходы - это очень интересно! Больше нигде я такого не видел.
Константин, спасибо за лекции!👍
ну это же просто шедевр! спасибо огромное за такой качественный материал!!!
Шикарная лекция - СПАСИБО !
Как жаль, что когда я учил С++ 20 лет назад, не было таких лекций и курсов.
Очень понравилось видео, на ютубе мало лекций подобного уровня на русском языке, продолжайте, пожалуйста!
Класс и Супер! Спасибо..
Спасибо большое!
Спасибо. Очень крутые лекции. Буду смотреть ещё. Качество сильно лучше, чем ранее
Спасибо за Ваш труд! Жаль, что можно поставить только один лайк.
человеческое спасибо вам, милый человек !!!!
С нетерпением жду продолжения!
Замечательные лекции. Пожалуйста продолжайте
Интересный курс. Задорное начало.
Велосипеды строк мне напомнили про Stroka и Wtroka от Yandex. Собственно, все крупные компании грешат велосипедами, когда всё своё.
Я понимаю, что поздновато комментировать, но format библиотека -- это не инициатива Microsoft, а внесённая в стандарт fmtlib Виктора Зверовича (P0645R10). Сейчас он, кажется, работает в Meta. Формат строковую интерполяции там взят, скорее, из Python форматирования. Такой вариант удобен, когда надо, например, повторно использовать аргументы. `{0} {1} {0}`.
В таком духе. Плюс, конечно большой от неё в том, что часть работы происходит во время компиляции. Не очень понятно, зачем автор решил её внести в стандарт, потому что эта библиотека сильно развивается на данном этапе. Её всегда можно использовать header-only или прилинковать статически , подтянув CMake-ом, например, или conan\vcpkg.
Лекция очень интересная :)
Курс супер, большое спасибо!
Большое спасибо! Очень интересная лекция
Это прекрасно!!!
Спасибо! Шикарная лекция и изложение. Впервые осознал сложность реализации строк. Разрабатывая на JS о подобном не задумываешься… 😅
очень интересные, живые лекции.
желаю успеха проекту!
СПАСИБО!!!
Ура!!!
Клёвый препод!
Отличная , лекция смотрю вас достаточно давно... Хотелось бы от вас увидеть вне лекций, проектирование программ на языке С++ :)
Мне тоже когда-нибудь хотелось бы такое записать.
@@tilirбуду рад от вас подобное увидеть. Мы понимаем, что вас достаточно работы на кафедре , фулл аптайм
1:11:26 Если совсем к слайдам придираться, после параметра Traits забыта запятая, аналогично в презентации для бакалавров (16-containers, 26 слайд, и еще там забыты ; после объявления классов, как и на 24 слайде)
Ничего не понятно, но очень интересно. Посмотрю что-нибудь попроще и ещё раз посмотрю это.
Ну наконецтаки!!!! Дождался!!!
Спасибо за лекцию. Про std::format вынужден не согласиться. Есть fmtlib - чудовищно популярная библиотека, которая легла в основу std::format. И все, кто хочет std::format(например, я) пока пользуются ей.
Ну и синтаксис у неё великолепен, в отличии от натыкивания модификаторов и обрубков строк в стрим в fmt::format задаётся единая форматная строка, из которой наглядно видно, как будет выглядеть результат, проверяет типизацию в компайл-тайме и выводит результат прилично быстрее stringstream'а.
В общем почему не добавляют std::format в стандартные библиотеки не знаю, но пока есть fmtlib - это не очень большая проблема.
Я за много лет ничего не слышал про эту чудовищно популярную библиотеку и не видел её применений. Видимо она популярна где-то за пределами моего мира, и в общем меня это устраивает. Ввод и вывод в C++ это iostreams.
А почему не printf()?
@@ИнтернетСпасётМир В первую очередь из-за кастомных форматтеров для объектов и полноценной проверки соответствия аргументов, а не на уровне костыля для компилятора. Ну и он полноценно интегрирован в C++, а так же есть вывод {}, когда он сам определяет, как выводить.
44:30 насколько помню, в кланговой libc++ начиная с 15 чтоль версии std::format таки завезли...
Я боюсь вы не правы: godbolt.org/z/ssc8Kzqr9
@@tilir посмотрела в релизноутах 15-ой версии- таки есть, но экспериментальное.
> P0645: The paper is implemented but still marked as an incomplete feature (the feature-test macro is not set and the libary is only available when built with -fexperimental-library). Not yet implemented LWG-issues will cause API and ABI breakage.
ну, значит уже вот-вот...
(и если добавить по вашей ссылке в аргументы -fexperimental-library - собирается)
Кажется легче было показать
auto* x = &"hello world";
auto* y = &5;
Казалось бы везде литералы, но почему то первое валидно .а второе нет, заставляет сразу внезапно осознать в чем разница между стринговым литералом и обычным, ну типа... Поинтер на нечто не выделенное в куче, но почему то это валидный код и он не провис
Без стандарта пожалуй отвечу на вопрос про nullptr
Для создания значения поинтера не нужно чтение значения nullptr, это работает по принципу тег-диспатчинга. Более того, чтобы создать копию значения nullptr тоже не нужно чтение значения из копии, так что кланг прав.
Более того, сама по себе возможность существования volatile int сомнительна, т.к. смысл имеют ссылки и указатели на volatile, а локальная переменная такого типа явно не может быть изменена никак кроме как с помощью УБ
Очень полезное дополнение. Я может быть внесу такую ревизию для следующих лет.
"Для создания значения поинтера не нужно чтение значения nullptr, это работает по принципу тег-диспатчинга."
Мне видится так, что это как раз не имеет значения, да вообщем то оба компилятора и явно читают значение. Да и нет никаких гарантий что такое nullptr.
А вот эта часть
"локальная переменная такого типа явно не может быть изменена никак кроме как с помощью УБ"
вроде как похожа на правду, а раз так то и "сайд эфектов" быть не может - следовательно можно вообще volatile удалить с нее (но этого ни один компилятор не делает).
а на счет использования std::stringstream вместо std::format -- при каждом вызове оператора
1:07:12 Константин, вроде никто еще не писал, но строчка с enum странная. 1) в конце инициализатора стоит ; что приводит к СЕ 2) у меня в godbolt gcc-12.2 x86-64 даёт SZ равный 1, то есть второй вариативный член union суть массив из одного CharT 3) еще драфт стандарта говорит, что внутри анонимного union "Each member-declaration in the member-specification of an anonymous union shall either define one or more public non-static data members or be a static_assert-declaration. Nested types, anonymous unions, and functions shall not be declared within an anonymous union.", но ни один из основных компиляторов не выполняет это требование (???)
Да, совершенно верно, она странная. На самом деле, там должно быть выражение которое евалуируется в 8, например, вот:
enum { SZ = 15 / sizeof(CharT) };
В некоторых источниках сказано что так оно реализовано в GCC. В clang - немного иначе и более компактно.
Могу поделиться источниками.
Отличная лекция.
Про список литературы:
Жаль что доклад про строку Фейсбука такой старый
У вас, Константин, ещё где-то была ссылка на видео, где докладчик пытался создать конструктор из двух строк.
Это кажется был Йосьютис. Но это скорее не к строкам это к rvalue ссылкам и семантике перемещения.
22:40 -- я не пойму, почему тут cmut и cinv может лежать в одной и той же памяти? -- если первое неконстантное, а второе константное -- тогда по сути компилятор бы делал возможным изменение константных значений без каста, -- что несомненно нарушало бы здравомысленную логикую
По одному или по разным адресам могут лежать литералы, которыми cmut и cinv инициализированы. Но конечно т.к. инициализация cmut это копирование, он сам будет по другому адресу чем литерал.
спасибо за ваши труды, спасибо за потрясающее качество курса! хотел бы спросить
есть ли упражнения, сопровождающие этот курс?
Упражнения все в бакалаврском курсе. Для магистрантов упражнения не нужны и даже немного оскорбительны они же все работают на профильных предприятиях.
Насчет std::format. У него хороший полет на маковском clang под M1
Казалось бы при чём тут компилятор и платформа. У него хороший полёт на всём что поддерживает C++20.
@@tilir Некоторые компиляторы которые "поддерживают C++20" по факту поддерживают не все фичи C++20. То ли дело stringstream который изначально с C++11...
Ну мы живём уже в 2024-м и пожалуй C++20 поддержан вокруг нас уже очень неплохо. Лекция записывалась два года назад в несколько другой реальности.
Веселый преподаватель))
👍
А вот что интересно const char* это указатель на память, но на какую память? То-есть где хранится строковый литерал, в какой области памяти. Явно же не в стеке и не в куче. В интернете я вычитал про сегметы в основном играет роль сегмент данных. И я в последнее время отношу строковый литерал именно туда, но так ли это.
Как раз на стеке
на счет std::format -- есть же отдельная открытая реализация на гитхабе. Почему бы ее не внести в stl для gcc? У меня снова флешбеки из прошлого, когда многие реализации почему то юзаются программистами не из stl...
Я думаю, что, помимо всего прочего, null-terminated строки лучше переносимы в смысле endianness
Здравствуйте, Константин.
Благодарю за лекцию, как всегда полезная и интересная.
Вопрос про последовательность изложения материала. Смотрю эту лекцию после вашего базового курса по С++. И вы рассказываете аудитории про type traits, и сами же говорите, что не все знают, что это, хотя курс называется магистерским.
Как так получается, что аудитория на магистерском курсе не знает, что вы рассказывали на базовом? Это как то связано с организацией учебного процесса в ВУЗе?
UPD: *про специализацию шаблонов рассказываете
Да связано. Базовый курс факультативный. Не вся магистерская группа там была.
ua-cam.com/video/9N_wJ7oIHDk/v-deo.html - так и нет появилось в комментах ответа.
Верно ли что прав clang, т.к. по стандарту присваивание b=a должно присвоить значение типа nullptr_t, т.е. nullptr, а в volatile переменной может оказаться все что угодно, но проблема с gcc - это только лишняя операция копирования из ячейки?
ребят такой вопрос (а если читает и автор, Константин, то и ему тоже): как новичку в c++, можно ли начать с этого курса или у Константина есть какой-то курс более вводный, так сказать. Просто немного путаюсь в плейлистах и роликах ютуба: "а точно ли это первый ролик", "а точно ли курс с нуля" и т.д, заранее спасибо.
В закреплённом посте на моём тг-канале приведены ссылки на три основных плейлиста: базовый по C, базовый по C++ и продвинутый по C++. Вот с них и начните. Если C уже знаете, пропускаете тот который по C.
t.me/cpp_lects_rus
P.S. cow всегда мне казалось крайне тупой затеей, ну правда, я что сам не знаю нужно мне писать туда или читать? Это очень легко контролируется мной и оно должно контролироваться, чтобы в коде показывать что я делаю
Итого берёшь и используешь string_view когда надо читать/ string когда нужно писать(или нужен объект строки сам в функции), собственно всё.
А cow это что то на уровне питона, когда можно передавать только "значения" а внутри язык сам решит что тебе лучше
p.s. и перфоманс видимо выигрывается только относительно состояния когда мы всегда копируем и нет sso
Не будьте слишком радикальны. Идея COW-строк ничем не хуже идеи shared pointers. И в том и в другом случае мы платим некоторой сложностью. Но мы платим за дело: за возможность не думать где у нас ссылочная семантика, а где семантика значений. Очень часто это большое облегчение, если вам есть о чём ещё подумать в вашей программе.
Не понимаю хейт format, {} - топ))) slf4j - логгер который используется как раз из за подстановок в фигурные скобки)))
большое спасибо за ваши труды! очень люблю ваши лекции!
надеюсь, вы всё-таки решите продолжать выкладывать свежий магистерский курс - уж очень хотелось бы послушать обновлённые лекции по концептам, range'ам, сопрограммам и прочим радостям двадцатого года. прошлые лекции ведь писались по "горячим следам" тогда ещё грядущего стандарта
Пора учить хеллоу-ворлд как `std::print("Привет, мир!");` 😁
Увы, но это плохая идея. Всё дело в том, что std::cout очень просто устроен: это объект класса с перегруженным оператором. А вот std::print устроен настолько сложно, что даже для многих опытных разработчиков объяснить его детали проблематично. Поэтому доя hello world он не подходит т.к. развивает магическое мышление, а у нас тут не пвйтон.
А можно ссылку на лекцию 1 где про типы поведения в компиляторе
Первая лекция в этом плейлисте: ua-cam.com/play/PL3BR09unfgcjJ2YUCgh62vgv_1maXcKuS.html
Подскажите пожалуйста, когда во второй части сказали "скачать стандарт" - это что именно имелось в виду? Нагуглить удалось что есть стандарты либо платные либо драфтовые - это верно? Помогите со ссылкой!
Я имел в виду final draft n4868
Про COW. Всё-таки было бы неплохо её в стандарте хоть как-то оставить. С++ всё-таки не только в многопоточной среде исполняется
Главный аргумент это не многопоточная среда. Даже в однопоточной среде главный аргумент это инвалидация указателей. Я если что тоже за COW строки в стандарте как политику для строк.
Я именно ввиду чтобы был отдельный тип для такой строки, можно и без скобок. SSO не везде поможет, а значит будет опять велосипедоделанье
@@giorgi_pa только для COW строк. Представьте что у вас есть две строки: S1 и S2 и они делят буфер A. Вы говорите S1[5]='a'. В этот момент для неё нужен отдельный буфер и теперь S2 владеет A, а для S1 выделился, скажем, B. В другом месте, то есть с другими адресами внутри.
Коровы должны давать молоко, а не вот это вот все.
Жалею, что поступал в бауманку, а не в физтех(
Reading an object designated by a volatile glvalue ... are all side effects which are changes in the state of the execution environment. ... 6.8.1? GCC прав?
Это вы о каком моменте видео? Хотя бы номер слайда...
@@tilir примерно 15:30. Я после даунтайма ещё не практиковался, а тут ваши лекции удачно попались :)
6.9.1, там 7 Reading an object designated by a volatile glvalue (7.2.1), modifying an object, calling a library I/O
function, or calling a function that does any of those operations are all side effects, which are changes in the
state of the execution environment. Evaluation of an expression (or a subexpression) in general includes both
value computations (including determining the identity of an object for glvalue evaluation and fetching a
value previously assigned to an object for prvalue evaluation) and initiation of side effects. When a call to a
library I/O function returns or an access through a volatile glvalue is evaluated the side effect is considered
complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile
access may not have completed yet.
Хотя забавно, в clang 8.0.1 асм такой же, как и в gcc, а в 9.0.0 уже как в примере. Вроде как, если я правильно нашёл, любое действие с volatile должно делать сайд-эффект.
@@fulloflolcats лучше ссылаться не на конкретный пункт а по символической ссылке. Пока ответ неверный, ищите дальше.
@@tilir Тогда предположу observable behavior. Можно соптимизировать, ничего не изменится. Но тогда никто не неправ. Стандартом это нормально не регламентируется (и не должно) и implementation defined. Сдаюсь короче :)
Посмотрите как lvalue-to-rvalue преобразует nullptr_t =)
кстати -- на счет инициализации статических данных -- не нашел нигде в стандарте с++20 (и в с++17) сведений о том, что статические поля инициализируются исключительно строго до функции main(). В стандарте указано, что статические данные инициилизируются до инициализации неглобальных данных и освобождаются строго после них. Никакой привязки именно к функции main() нет.
На самом деле если не лезть в бутылку, то стандарт примерно это и говорит.
[basic.start.dynamic]
It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized.
То есть вроде как откладывать можно, но не дальше, чем использование любой не-инлайн функции или переменной в том же модуле. Ясно, что это исключение сделано только и исключительно для shared object, где действительно при подгрузке модуля переменные инициализируются после main где-то при dlopen.
Так что думать об инициализации как о чём-то происходящем "до main" -- в целом вполне правильно с понятными оговорками.
Жалею, что не учился на РТ, сам с фупма и такой дичи не видал, но точно бы остался если бы она была.
Коаны для медитации:
Литерал - константа времени компиляции.