Open apolukhin opened 3 years ago
BlackMat MATov, 26 декабря 2018, 14:03 П - перформанс
Дмитрий, 26 декабря 2018, 23:15
Был случай когда указатель забыли проинициализировать ...
Используйте smart pointer
valera_ee, 27 декабря 2018, 11:39 Дмитрий, сейчас, конечно только ими ипользуюсь, но что делать с сотнями тысяч строк старого кода? Их все разом переписать не получится, это процесс долгий и затратный.
al-mission-2016, 28 декабря 2018, 1:33 При проектировании языка программирования приходится решать дилемму - производительность vs "меньше ошибок по невнимательности". Когда в конце 60х изобретали С, инициализация по-умолчанию была непозволительной роскошью.
Относительно инициализации дилемма такова: [A] по-умолчанию ничего не инициализируется; безопасные начальные значения - это ответственность программиста; [B] всё инициализируется по-умолчанию, за исключением случаев, когда явно указано, что инициализировать не надо.
В С++ очевидно принят подход [А] и это решение слишком фундаментально, чтобы его можно было поменять. Можно только помочь бороться с последствиями. :)
Причины подхода [А] в С++: 1) Совместимость с языком С - там нет инициализации по-умолчанию. 2) Производительность = как основа философии С/С++. Например, в 3D-app требуется создать 1'000'000 треугольников. Нулевые значения смысла не имеют, всё равно они будут перезаписаны при загрузке сцены. Здесь нулевая инициализация - performance hit. Компилятор далеко не всегда может устранить лишние присваивания. 3) требования обратной совместимости с предшествующими версиями С++, чтобы избежать изменения поведения старого кода, при компиляции в режиме С++11++. 4) для пользовательских типов имеются: конструкторы и их списки инициализации, а в С++11/14 добавили инициализация членов-данных при их декларации. Этих инструментов достаточно, чтобы обеспечить значения по-умолчанию, где это необходимо. Кроме того, локальные переменные в С++ рекомендуется создавать как можно ближе к месту их использования и соответственно сразу инициализировать их разумными значениями.
Теперь предположим, что мы изменили С++, введя инициализацию по-умолчанию. Одновременно потребуется добавлять механизм, позволяющий явно указать, как не инициализировать в случаях, когда важна производительность, а значения по-умолчанию не подходят. Напр.:
int x = void; // as in D-language
В результате придётся дорабатывать тот legacy-code, в котором инициализация по-умолчанию начнёт бить по производительности! То есть решая проблему одних, мы создадим проблему другим. Не стоит оно того. :)
valera_ee
Попробуйте статические анализаторы кода.
valera_ee, 28 декабря 2018, 7:19 al-mission-2016, это всё, конечно, хорошо, но вместо голых быстрых указателей мы начали использовать медленный, но безопасный вариант умных указателей, и производительность падает, вместо голых массивов std::vector и это всё замедляет программу, так о какой производительности тогда говорить? Сейчас вообще есть constexpr, мы получили возможность инициализировать константы на этапе компиляции, так , а что мешает делать тоже самое для полей класса у которых отсутствует явная инициализация?
Fihtangolz, 29 декабря 2018, 15:29 valera_ee, хз я вообше предлагаю просто выкинуть фундаментальные типы написать классы int, float, double, оставить только что то типа byte в качестве фундаментального типа, ну собственно дальше кому надо сделают инициализацию по умолчанию
al-mission-2016, 2 января 2019, 8:19
Fihtangolz, в рамках собственного проекта можно делать что угодно, хоть на потолке спать. (: Только вряд ли стоит тащить в стандарт языка обратно-несовместимые вещи, как предложил Валерий. :)
valera_ee,
ваше предложение означает поменять правила игры на лету, когда решение уже давно принято и куча легаси кода полагается на него.
"что мешает делать тоже самое для полей класса у которых отсутствует явная инициализация?"
Мешает обратная совместимость. Часть кода (правда довольно специфичного) просто поломается. Например, поломается код, который принципиально предполагает (в соответствии с нынешним стандартом), что если поле класса нигде явно не проинициализированно, то компилятор в него точно ничего не запишет. Это важно для embedded/firmware программирования. Используя placement-new (и volatile) можно отобразить структуру, т.е. её члены-данные, на память, которая является пространством портов ввода-вывода. Теперь получаем, что "старые" версии компилятора ничего не писали в поля-порты без ведома программиста. А "новый" компилятор, инициализируя поля значениями по-умолчанию, запишет в порты нули! В принципе, этого примера достаточно, чтобы отклонить ваше предложение.
По производительности. Да, компьютеры стали быстрее, память дешевле, можно позволить размен - чуть медленнее софт, зато потенциально чуть меньше ошибок, код пишется быстрее и т.д. Для многих проектов это вполне приемлемо. Но заметьте, std::vector, умные указатели и т.п. - это опция, у нас есть выбор. Если нужна максимальная производительность, можно обойтись без них. А ваше предложение - всегда инициализировать - принудительно. Кстати, некоторые game-dev'ы, типа EA, писали в своё время собственные версии STL, когда их не устраивала производительность контейнеров общего назначения.
В https://wg21.link/P2723 делают автоматическую инициализацию переменных, в рамках того же предложения хотят добавить механизм для явной инициализации мусором
Перенос предложения: голоса +6, -13 Автор идеи: valera_ee
Работая над большим проектом, который начал своё начало ещё до С++11, столкнулся с проблемами адаптации кода под новый стандарт. Все поля класса инициализируются в конструкторе или в списке инициализации, около 95% такой инициализации это присваивание переменным класса 0 или NULL.
Сейчас можно прописать инициализацию в заголовочном файле:
Возникает логичный вопрос, почему изначально не инициализировать базовые типы нулём, а указатели значением nullptr ? А там где требуется указать значение, отличное от значения по умолчанию, там прописывать вручную.
Был случай когда указатель забыли проинициализировать и там по мусорному адресу происходило обращение и программа не падала при этом, если бы указатель был нулевым, то ошибку обнаружили бы сразу.