- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
class UnitedFigure : public Figure {
Figure &f1;
Figure &f2;
public:
UnitedFigure (Figure &_f1, Figure &_f2) : f1(_f1), f2(_f2) {}
double distance_to(const Point &p) const override {
return std::min(f1.distance_to(p), f2.distance_to(p));
}
}
> прекрасную возможность выстрелить себе в ногу
Чем ссылочные поля отличаются от полей-указателей?
?
Внутри main создает временный объект с 42, и должен бы по идее разрушиться сразу, но остается жить?
Кажется, до 11 такого не было, и надо было вручную делать
но это не точно.
хотя пишут ворнинг
в смысле не бывает
UB. ССЗБ.
В С++ же нет нулл сейфти, это же не котлин. Ты обязан проверить, что указатель не указывает на говно, прежде чем покласть его результат в ссылку
https://govnokod.ru/26958#comment575830
ну ты же понял, что имелось ввиду, не?
Когда я пишу
int& foo = *some_shit_that_returns_null()
там под капотом в foo оказывается адрес null, и при следующем обращении случается бугор
Я не спорю, что UB. Просто забавно, что оно как-бы заметено под ковёр из за сахара.
В этом-то и дело. Багор случается сразу же, как только ты разыменовываешь nullptr. Просто его последствия начинают проявляться позже.
Перефразируя j123123 (https://govnokod.ru/26809#comment575323):
>>> Если ты в крестах используешь какую-то сраную ебучую хуйню, типа разыменования указателя, то ты сам дурак должен соблюдать предельную осторожность с этой хуйней, и вся ответственность за segmentation fault и прочие подобные спецэффекты лежат на тебе. И нехуй в этом винить ссылки
Сразу случается UB, а багор случается чуть позже (хотя наверное может и сразу случиться в теории)
Я так понимаю, что именно это им не нравится.
На как по мне это сахарок с ёбнутыми значками.
Всё там бывает, надо просто уметь. https://wandbox.org/permlink/N8evr3fCGLXDwEMt
Эти ссылки - просто сахарок над указателями
int *crap = (int *)malloc(100500);
на котором этот самый malloc обсирается и возвращает NULL, и потом в некую хуйню передается по ссылке crap[0]
и разыменование нулевой хуйни произойдет по факту не в том месте, где вызвана хуйня shit(crap[0]) а внутри самой функции shit(), которая с этой ссылкой будет что-то делать
>и потом в некую хуйню передается по ссылке crap[0]
лол, то есть можно передать уже говно, и узнать о том, что ты передал говно через три часа в другом месте?
По сути у тебя будет ссылка на нул, да)
Проверил. Такая хуйня скомпилировалсь, и упала. Какой багор))))
Типа да, при передаче по указателю ты можешь нормально проверить, что указатель там не NULL, а по ссылке - хуй там. Но NULL там быть все же может.
Ссылки - просто сахарок над указателями для заедушных питушков, чтоб поменьше * писать
Если ты поклал в ссылку нул, то ты сам кривой.
В моем примере видимо надо так
Можно, разрешаю. https://wandbox.org/permlink/edO6vo7o3ntWfZVJ
https://stackoverflow.com/a/9263728
а ты грил нельзя на хуйню проверить
Ну так действительно нельзя
Там будет такая же хуйня с варнингом на строчке if (&bar == NULL)
prog.cc:11:18: warning: the compiler can assume that the address of 'bar' will never be NULL [-Waddress]
reference cannot be bound to dereferenced null pointer in well-defined c++ code
То есть катсинг-то сам по себе валиден (взять адрес того, на кого указывает ссылка), а вот проверка оного на нул -- варнинг
Ну как бы да, компилятор имеет право считать, что раз у нас ссылка, то это точно что-то валидное, и NULL там быть не может.
компилятор имеет полное право мою проверку выкинуть, и код упадет
> *(int *)0
У тебя произошло UB, и что там дальше (да и раньше тоже) происходит — никого не волнует.
В well-formed программе на крестах nullptr в ссылке быть не может никогда.
>> *(int *)0
>У тебя произошло UB
Если внимательно посмотреть, я использую особую опцию "-fno-delete-null-pointer-checks" от которой компилятор ложит хер на ту часть стандарта, которая запрещает разыменовывать NULL.
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
> -fdelete-null-pointer-checks
>
> Assume that programs cannot safely dereference null pointers, and that no code or data element resides at address zero. This option enables simple constant folding optimizations at all optimization levels. In addition, other optimization passes in GCC use this flag to control global dataflow analyses that eliminate useless checks for null pointers; these assume that a memory access to address zero always results in a trap, so that if a pointer is checked after it has already been dereferenced, it cannot be null.
>
> Note however that in some environments this assumption is not true. Use -fno-delete-null-pointer-checks to disable this optimization for programs that depend on that behavior.
>
> This option is enabled by default on most targets. On Nios II ELF, it defaults to off. On AVR, CR16, and MSP430, this option is completely disabled.
>
> Passes that use the dataflow information are enabled independently at different optimization levels.
Но видимо этот флаг не запрещает компилятору предполагать, что ссылка не может быть с NULL.
Надо просто ввести новую опцию -fallow-null-in-references
…то ты пишешь не на «C++», а на другом языке. С тем же успехом я могу ругать сишные структуры за какие-то багры в «Cython».
> где прочитать или записать хуйню по нулевому указателю вполне может иметь смысл
По Стандарту, кстати, никакого «нулевого» указателя не существует. Конкретный адрес nullptr и NULL выбирает платформа. Синтаксис «T * ptr = 0;» является синтаксическим сахаром:
§ 7.3.11/1 (N4842)
Именно поэтому читать-записывать по нулевому адресу тебе никто* не мешает:
* При условии, что там лежит валидный объект.
Только вот тогда получается так, что на настоящем «C++» не пишет вообще никто, т.к. ни один компилятор крестоговна на данный момент не реализует стандарт на 100%
https://modern-sql.com/standard/levels
> The SQL standard is huge. More than 4300 pages in its SQL:2016 incarnation. No single implementation can ever implement all features.0 Even in the early releases, such as SQL-92, the SQL standard defined different conformance levels so that vendors can claim conformance to a subset of the standard.
Почему кстати в стандарт крестоговна не ввели эти «conformance levels»? По-моему вполне логичный шаг.
ведь компилятор C++ не должен отвечать за другие языки.
в чём тут подвох
если у него реально другой язык, почему крестовый компилятор успешно компилирует такие исходники?
может, проблема просто в обилии UB'ов?
Термин — да, поведение — нет.
Как только в твоей программе случается UB — она перестаёт быть валидной программой на «C++», для которой Стандарт определяет какое-либо поведение.
> почему крестовый компилятор успешно компилирует такие исходники?
Потому что для программы с UB крестовый компилятор может делать что угодно!
> может, проблема просто в обилии UB'ов?
Это совершенно другая проблема.
то есть компилятор C++ может взять код не на C++ и скомпилировать из него какую-то ебалу
хорошо, что я на таком не пишу
Как, впрочем, и няшная сишка: там тоже есть UB и оно точно так же может через карман укусить за яйца. С другой стороны, в §J.2 (N2346) приведён полный список сишных UB, так что их можно более-менее заучить и не допускать. С третьем стороны, этот список занимает десять страниц A4.
Емнип, там офигенные вещи были в духе "название хедера не должно начинаться с цифры". Вот назовёшь хедер 1.h и получишь UB.
ломалось бы на этапе линковки или даже раньше
Ну либо вместо голого указателя возвращать какой-нибудь non_null_ptr<T>. Или ссылку, лол.
Я её выдумал. Но пишется за пару минут. В конструкторе проверишь, что не нулл и бросишь исключение. А дальше можно таскать без проверок и потерь пирфоманса.
Ну по-хорошему да. Не верить же автору сторонней либы на слово? Тем более сишные либы так сигналят об ошибке и тебе один хер проверять. А в крестах тебе голый указатель не так уж часто возвращают.
Если ты уверен, что get_petuhz() тебе никогда не вернёт nullptr — можешь делать так безо всяких проверок. В этом и есть смысл крестов (да и няшной тоже): ты можешь делать «опасные» операции безо всяких проверок, если считаешь, что они всегда будут корректны.
Однако если твоя уверенность тебя подведёт и get_petuhz() таки вернёт nullptr — ты получишь UB, и дальше твоя программа может делать абсолютно что угодно.
А потому что только Программист знает, что валидно, а что нет.
Он царь и бог, а не житель анально огороженной крепости с надсмотрщиком как в джава
а я придерживаюсь тех же взглядов. Компилятор/интерпретатор должен только проверять корректность синтаксиса, и никак не обучать тебя каким-то типизациям и, тем более, заставлять тебя удалять неиспользуемые переменные (как в "Go").
Так даёт-то это что?
библиотека это уже бинарь
Текст стандарта крестоговна написан на английском и не является строго формализованным описанием, так что там еще хуй поймешь, можно над каким-то пунктом рассуждать как жиды над торой, что там говностандартизаторы в этом пункте имели в виду. Надо написать четкую формальную спецификацию, чтоб никаких разночтений не было, потом уже говорить, что можно писать на каком-то мифическом «C++»
> Надо написать четкую формальную спецификацию
Написали. Называется «Стандарт».
> разночтений
Приведи реальный пример разночтений в Стандарте.
Это не четкая формальная спецификация. Это текстовая человекочитаемая хуйня на естественном языке, которую можно по-разному понять и проинтерпретировать своим мозгом.
> Приведи реальный пример разночтений в Стандарте.
Могу привести реальный пример, когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать
> Могу привести реальный пример
Ну приведи.
> Давайте с memcpy, с ним проще. Я смотрю по C++17 draft, но для простоты и тех, кто не хочет грузить 1500-страничные пдфки, даю ссылки на онлайн-версию, где стандарт уже немного другой.
> Так вот, 6.8/2 и /3 говорят, что вы можете делать memcpy для объектов trivially copyable типов (в частности, если они не являются подобъектами), даже если они не содержат валидного значения. И как мы видим из 11.2/1, наличие конструктора по умолчанию никак не влияет на свойство trivially copyable.
> Надеюсь, этого достаточно, чтобы разобраться с memcpy.
> А вот с memset всё интереснее. Он в стандарте упоминается всего несколько раз, и все эти разы — без описания семантики. Поэтому вопрос о том, что разрешено делать с memset, является совсем неочевидным. Ответ «memset в коде на плюсах использовать нельзя вообще», похоже, стандарту не противоречит.
И в ответе:
> Ну в самом же деле, нельзя же ожидать, чтобы в стандарте были перечислены вообще все допустимые случаи использования любых комбинаций функций из стандартной библиотеки.
Какой багор )))
Поэтому я за «Brainfuck».
§ 21.5.3/1 (N4842)
Идём в «C standard», читаем:
(N2346)
Всё, никаких разночтений.
O_o
Какой багор )))
Надо четко написать, что такие-то функции ведут себя точно так же, как ведут себя функции Си такого-то стандарта. А что такое meaning какого-то хеадера сишки? Просто определение функций, а что они делает - хуй знает. Это вам не крестоговно, когда там какие-то шаблоны с кодом запилены.
>>> The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.
Тут разве что приебаться можно к «first n characters of the object pointed to by s», но это нужно хорошенько задрочить крестовый object representation или как его, а там дохуя листов A4 формального английского, который нашему отделу чтения и парсинга обрабатывать лень.
contents - содержимое. Там содержатся какие-то определения функций. Т.е. инклудя <cstring> мы инклудим то же, что и в <string.h>
meaning - значение. Ну т.е. смысл того что заинклужено. А смысл в хедере там такой, что вот такие-то функции есть, которые принимают такие-то аргументы и возвращает такую-то хуйню. Хедер сам по себе не описывает то, что конкретно какая функция делает. Так что надо четко сказать, что функии, определенные в таком-то хедере, делают то же самое, что они делают в сишечке такого-то стандарта.
На самом деле хорошая приёбка, но, тем не менее, Стандарт может противостоять даже таким дотошным людям!
§ 2/2
> Ну может это означает что-то в духе
Всё есть в Стандарте.
> когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать
И тем не менее, после качественной раскопки Стандарта разночтений выявлено всё ещё не было. Отсутствие строгого определения слова «meaning» полностью компенсируется примечанием 1.
Научная фантастика и научная реальность в информатике
Эдсгер В. Дейкстра
...
Чуть раньше я упомянул плохую документацию системы как внутреннее ограничение надежности, с которой система может быть использована механически в более широком контексте. Теперь самое время указать, что привлечение технического писателя редко является выходом из положения; в сущности, это не более как признание того, что разработчики системы в некотором роде функционально безграмотны. Обычно даже целая армия технических писателей не может справиться с задачей, поскольку система становится столь сложной, что не поддается точному описанию.
Если бы в браузер была встроена ада, то все бы на ней писали, и текли, и не жужжали, и меньше было бы в мире undefined, Nan и [Object object].
Потому что статическая типизация позволяет отловить больше ошибок на уровне комплияции. Это же очевидно. Именно потому MS изобрёл TS.
это означает что бандл у меня поделен на файлы, файлы подгружаются асинхронно, для работы сайта в первую секунду нужен один, а все остальные догружаются в течении минуты, а какие-то через 10 минут
при этом в коде файлы считают друг друга модулями
как это реализовать на компилируемых языках?
Хуяндл.
меня наебали?
Ось сразу посылает нахуй, если DLL указана в таблице импорта. Но этот способ далеко не единственный.
Второй способ — вызов функций LoadLibrary и GetProcAddress. Этим способом можно подгрузить DLL в любой момент и не упасть, если она не загрузится.
А в «Линуксе» есть dlopen.
А если на помойке нашёл - ну подизасмишь.
как мне метод позвать или функцию?
Опыт и везение. Что ещё защищает сишника?
Список символов получить можно. А вот семантику параметров функций нужно знать. В JS ты же тоже не знаешь, для чего какой аргумент у функции из чужого скрипта.
Как что-то плохое. Немного дизасмишь саму длл, немного дизасмишь или дебажишь проги, которые ее юзали.
Если там не дичь какая-то, то часто удаётся понять суть аргументов.
Малость дизасмишь проги, которые её юзали.
Много примеров использования получаешь.
Это в нашей чеховской-кибальчеховской все-все знают.
или время запуска?
j123123 так мастерски доёбуется до С++, что из него вышел бы отличный кретостандартизатор.
Ну так там это и написано. Для каждого хедера из стандартной либы (что крестов, что няшной) есть отдельный раздел, в котором описываются meaning соответствующих функций.
В крестовом Стандарте в описании <cstring> даже ссылка есть на соответствующий пункт няшного («See also: ISO C 7.24»).
Там же про meaning хедера говорится, а не про meaning функций.
Ну и вот мы тут как раз еще один пример получили, когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать, как ты и просил в https://govnokod.ru/26958#comment575919
> даже ссылка есть на соответствующий пункт няшного («See also: ISO C 7.24»).
Мало ли что это может значить? Ну может это означает что-то в духе "ну вот может ну нахуй это крестоговно, вот посмотрите лучше стандарт сишки, там прикольней написано".
Какая однозначность )))
> int value_at_zero = *(int *)(1 - 1);
Тут кстати можно не согласиться.
Если хуйня «(1 - 1)» после вычислений дает то же, что и дает NULL (допустим если в хедере есть «#define NULL 0», и при этом из курса школьной математики нам известно, что «1-1=0»), то получим UB (даже если там валидный объект). Если «*(int *)(1 - 1)» дает ту же хуйню, что и «*(int *)nullptr» - получем ту же UB хуйню (даже если там валидный объект)
В этом и весь смысл: (1 - 1) и 0 в контексте нулевого указателя — это разные вещи. Простой нолик-литерал — это синтаксический сахар, к нулевому адресу не имеющий никакого отношения. Поэтому из NULL == 0 вовсе не следует, что (int *)(1 - 1) — это нулевой указатель.
> Если «*(int *)(1 - 1)» дает ту же хуйню, что и «*(int *)nullptr» - получем ту же UB хуйню
А так будет только тогда, когда компилятор считает нулевой адрес за nullptr. Очевидно, если на какой-то платформе нулевой адрес валиден, то компилятор nullptr в него раскрывать не будет. Ну, если его не лалки анскильные писали, конечно.
Какой нуллптр )))
>>> There was a strong consensus among the CWG that only the literal 0 should be considered a null pointer constant, not any arbitrary zero-valued constant expression as is currently specified.
Причём до C++11 нулевым указателем считалась любое нулевое константное выражение, что приводило к такому багру:
Есть реальные примеры, где это были б разные вещи?
https://wandbox.org/permlink/awAHb63ePcdv8Jal - я что-то не нашел.
>>> A null pointer constant is an integer literal (5.13.2) with value zero
Ну и https://wg21.cmeerw.net/cwg/issue903 ещё.
в крестах может вывести "sosnoole!\n" ?
Ну и хуйня ваши кресты.
> Ну и хуйня ваши кресты.
Ну а как ещё соблюсти два условия:
1) Иметь «нулевой» указатель nullptr, который на текущей платформе всегда будет невалиден;
2) Иметь возможность писать в любые адреса, поддерживаемые платформой, включая 0.
?
В теории можно изобрести такую платформу, где абсолютно все указатели будут валидны, так что это условие по-сути своей - хуйня полная.
> 2) Иметь возможность писать в любые адреса, поддерживаемые платформой, включая 0.
Это можно было б решить какой-нибудь нестандартной хуйней, например специальным оператором разыменования или встроенной функцией, которая подразумевает что через нее можно можно и нулл разыменовать, и нихуя плохого в этом нет. Типа вместо
int hui = *(* int )0;
делаем
int hui = __buildtin_superduper_dereference((* int )0);
А на практике такая платформа нахуй не нужна.
Нулевой указатель нам нужен не для того, чтобы UB генерировать, а чтобы на него, внезапно, проверять. Вот есть у нас malloc(), она нам может вернуть либо указатель на выделенную память, либо nullptr/NULL в случае, если что-то пошло не так. Если у нас все указатели валидны — мы сосём хуй.
> специальным оператором разыменования
Ну и плодим никому не нужные сущности. Вместо этого разумнее было бы лишние сущности удалить, и за нулевой указатель считать только платформозависимый NULL/nullptr. Тогда мы спокойно можем писать по любому валидному числовому адресу, и никаких багров не возникает.
Разумеется.
§ 7.3.14/1 (N4842)
Какой багор))
В текущих крестах — да, реальный адрес будет 0xFFF….
> if(foo == 0)
0 неявно скастится к уко-ко-козателю и всё будет работать правильно.
Эта хуйня без NULL-питухов решается - в malloc просто возвращаем структуру, которая состоит из bool и из поинтера. Если в буле false то значит malloc обосрался с выделением памяти, если в буле true то значит все норм, и из другого члена этот поинтер читаем и чето с ним делаем.
Только вот есть проблема: обычно размер указателя равен размеру регистра, поэтому твоя структурка в [er]?ax не поместится. Как результат — придётся на каждый вызов любой функции, потенциально возвращающей NULL, лишний раз дрочить память, а это пиздец пирфомансу.
На практике нахуй не нужны языки, которые указывают, какие платформы нужны, а какие нет.
Если взять например 8-bit AVR говноконтроллеры и почитать memory map из даташита, то там на нулевых адресах хранятся значения регистров, т.е. регистры можно прочитать из памяти таким вот образом. Если используется malloc() хуйня, то конечно же она в регистрах нихуя выделять не должна, так что для обозначения того, что malloc() обосрался, вполне можно использовать адрес 0x0000, и для этого не надо никакой хуйни с гарантировано невалидными адресами, которые разыменовывать нельзя, достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
И шо, все остальные адреса валидные? Прямо от 0 до 0xFFF…?
> достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
Ок, хочу функцию
И чтобы она на тех контроллерах, на которых маппинг регистров в память поддерживается, возвращала мне этот адрес, а на тех, где не поддерживается — об этом сообщала. Вызывать её будем триллион раз в час.
Ну вот тут https://scienceprog.com/avr-microcontroller-memory-map/ написано что начиная с RAMEND+1 адреса идет External RAM вплоть до 0xFFFF. Если ее реально всю дозаполнить реальной памятью, то тогда похоже что да, все адреса там так или иначе будут за что-то отвечать.
>чтобы она на тех контроллерах, на которых маппинг регистров в память поддерживается, возвращала мне этот адрес, а на тех, где не поддерживается — об этом сообщала.
А нахуя? Почему б тебе не узнать о неподдерживаемости на этапе компиляции (или на этапе чтения даташитов на конкретный говноконтроллер)?
Принимается. Да, у 16-битных (и меньше) контроллеров с лишней памятью проблемы. Их владельцам можно посоветовать либо использовать компилятор, производитель которого явно задекларировал, что в нём обращаться к NULL можно, либо хуярить асмовставки, благо из них обращаться к любым адресам никто не запрещает.
> А нахуя? Почему б тебе не узнать о неподдерживаемости на этапе компиляции (или на этапе чтения даташитов на конкретный говноконтроллер)?
Потому что надо.
Ну а вообще я к тому, что вот это:
>> достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
— плохое, неконсистентное решение. Если я могу прочитать данные по какому-то указателю, то почему он должен считаться невалидным?
А зачем для этого считать (void *)0 не тем же самым, что и (void *)(1-1) ? Ну пусть бы был какой-то nullptr который на одной платформе равен какому-нибудь 0xFFFFFFFF, на второй равен 0xDEADC0DE, на какой-то другой - еще какой-то хуйне, зачем его синонимировать с литералом 0? Чтоб с сишкой была совместимость?
В крестах же NULLа не было в отличие от сишки.
«GCC» Стандарт понимает правильно и выдаёт вышеуказанные ошибки. А вот «Visual Studio» последней версии на них кладёт болт и успешно компилирует все три примера. Какой багор )))
«GCC» всё делает правильно и выводит «Pointer!/Pointer!/.../...»: https://wandbox.org/permlink/5HqRbFjgqNgUraDk.
А вот «Visual Studio» анскильно выдаёт четыре «Pointer!»: https://gcc.godbolt.org/z/W8hdY7 (cout заменил на няшный puts, а то там пиздец килобайты асма вылезли). Какой багорище )))
Даже если у тебя какая-то платформа, где нулл можно юзать, ну положи туда какую-то структуру, на которую ты никогда не будешь брать указатели, которые могут быть невалидными. Ту же таблицу прерываний. Всяко что-то такое у тебя есть.
И не надо портить платформу и городить костыли на ровном месте.
И явный UB про разадресацию nullptr тоже можно убрать. Он ничем не отличается от любого другого указателя на мусор.
Какие костыли-то? Отдельный NULL/nullptr без привязки к конкретным числам — вполне себе заебись решение.
> И UB про разадресацию nullptr тоже можно убрать.
UB нельзя убирать, UB — это священная корова оптимизации!
А UB про "специальное значение", имхо, пользы не приносит. Только вред и уязвимости в духе выбрасывания проверки на нулл потому что я уже обратился.
Таблица прерываний, загрузочный код и т.п.
Т.е. к нулю вроде и есть обращения, но их буквально пара штук на всю ось и они никогда не содержат проверку на нулл.
Зачем? Зачем?
Где тут повышения требования к скилльности прогера?
Дык в любом языке с nullable ссылками дошли до того, что неплохо бы иметь специальное значение для пустой ссылки.
> int* q = (int*)i; //вот что тут будет?
С принудительным кастом — указатель на адрес 0.
> if (q == NULL) //а тут что?
Зависит от платформы.
Проблема не в принудительном касте, проблема в неявном. По-хорошему, надо было полностью запретить неявные касты из любых чисел в указатели. Хочешь инициализировать указатель пустым значением — пиши «ptr = NULL», а не выёбывайся с «ptr = 0».
Но, разумеется, теперь Боржоми пить поздно, совместимость с сишкой выкинуть не получится.
А без него, к счастью, не скомпилится даже сейчас.
Дык NULL — это по определению невалидный адрес.
> в духе выбрасывания проверки на нулл потому что я уже обратился
Дык уязвимость-то будет не в выбрасывании проверки на нулл, а в самом обращении. После обращения к указателю проверка на нулл полностью бессмыслена.
Скажем так, это просто адрес, который не может быть выделен аллокатором, описанным в стандарте (ну и не может принадлежать локалке и т.п.) Поэтому я его могу юзать как маркер пустоты или как маркер ошибки. И это удобно для всяких структур данных.
Но он, имхо, ничуть не более невалидный, чем указатель на какой-нибудь ROM или MMIO, который я тоже по стандарту получить и юзать не могу, лол.
Зачем его делать пиздец-пиздец невалидным и особенным - я х.з.
Дык он и никакой не особенный. Обращение к нему — точно такое же UB, как и обращение к любому другому невалидному адресу.
>> В код по ошибке просочилось чтение.
>> А дальше пошло исполнение кода.
Какое исполнение-то? Чтение тебе кинуло SIGINT и всё, привет.
На то и UB. Невалидный согласно стандарту адрес вполне может быть физически валидным.
Почему нулл то в этом плане особенный? Потому что весь код засрали проверками на него, а теперь тормозит?
А какие ещё адреса согласно Стандарту невалидны?
> Почему нулл то в этом плане особенный?
Потому что компилятор не знает и знать никак не может, какие адреса у тебя там валидные, а какие нет.
Откуда компилятор должен узнать, что по 0x1234 у тебя ничего валидного не лежит?
В код по ошибке просочилось чтение. Дальше была проверка, которая остановила бы код. Но гцц ее выкинул. А дальше пошло исполнение кода.
Обращение к *p не должно создавать факт "p не нулл", имхо.
§ 9.3.3.2/5 (N4842)
Так что жаловаться на null в ссылках — это как сделать строку без \0 в конце, а потом ругать «strlen()» за то, что она падает.
> и устроить true == false
Кстати, в прошлом году на ГК это обсуждали: делали memcpy() в буль-буль переменную и наблюдали за весёлыми эффектами на разных компиляторах. Кажется, там ещё какой-то конпелятор проверял чётность буль-буля и 2 считал за false.
Присвоишь ты в это поле ссылку на объект в другом скопе, он уничтожится и получишь SEGFAULT, и будешь потом долго искать в чем дело, а найдя будешь переписывать свой монолит.
> по твоему поля всегда должны копироваться чтоли?
умные указатели, RAII, а не это уж точно.
, кроме того, что ссылки тебе гарантируют null-safety?
А ссылку не можешь (точнее можешь, но компилятор может такую проверку выкинуть, бо будет считать, что она всегда фолс))
Но я не защищаю эту позицию. Я не крестовик, но мне тоже нравится null safety. Во всяком случае в джавах и котлинах мне нравится знать, что поле никогда не может быть нулом, и не проверять его каждый раз, как дурак
> Во всяком случае в джавах и котлинах мне нравится знать, что поле никогда не может быть нулом, и не проверять его каждый раз, как дурак
Подтверждаю.
Кстати, если уж развивать мысль — в «Ко-ко» же можно какой-нибудь грязной рефлексией в поле типа T записать null?
наплодили шлюхоаккаунтов, ну шо за люди, блять...
ну на
ХРЮЮЮЮ
С ссылками и поинтерами вообще такая проблема есть в крестах, угу.
>умные указатели
Ну так используй умные указатели в полях, это же можно наверное?
Умные указатели нужны тогда, когда наш класс владеет объектом (за исключением std::weak_ptr, но это специфическая штука). А когда класс должен ссылаться на какой-то объект, очевидно, приходится использовать либо указатели (и ловить багры от nullptr), либо ссылки (и ловить багры от невозможности изменить объект, на который указывает ссылка).
> Для данного класса какой-нибудь unique вполне сойдёт.
А вот не факт. Я, может, не хочу ебать кучу, а хочу
.
Десктоп, было такое?
правда что именно там было на стеке яне помню
Тогда всегда пишешь как для кучи, а конпелятор сам разберётся.
Жабий жит вроде умеет такое. Кресты пока нет, но собираются добавить в стандарт возможность выпиливать пару new/delete.
потому что иначе был бы ад: яхочу передать структуру из двух интов (например Point), и должен в кучу срать?
нувот джит умеет доказать, что ссылка не утекает и вот
типа я такой сру в кучу, а он ESP вертит
Апгрейд мув-семантики?
Они ещё предлагают похожую технику, если конструктор+деструктор тривиальный, то объект можно копировать через memcpy.
Особенно поможет стд::вектору, чтобы при удвоениях делать realloc.
>>> А, ну да, это ж кресты, тут думать надо.[/color]
>думать надо.
C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений. Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист. Умение героически преодолевать трудности, которые создает твой собственный инструмент, вместо того, чтобы решать непосредственно прикладную задачу, в современном мире ценится разве что только среди прыщавых сосок. Работодатель же это сомнительное умение не ценит, и совершенно справедливо.
блять
как ты мог насоздавать фаек с детским паролем, ты ж не уёбок
Ты вот кладешь телефон на работе на стол? Как ты знаешь, что его не спиздят?
и машину всегда лочу
нахуй надо
Даже когда один дома?
зато пароль у меня не 123
Ну вот зачем ты выдал инфу о своём пароле? Теперь на 1 вариант меньше перебирать.
раки набрутили пароли со старых древних акков и время от времени с них срут
набрутили потому, что пароли там типа 123
Макака каждый раз, когда начинают срать, первым кричит, что "опять эти раки"
но всем файкам поставил именно 123 в качестве пароля
наверное, чтобы ракам было через пару лет удобнее набрутить ещё учёток