Здравствуйте, Mr.Delphist, Вы писали:
MD>Найдите 10 отличий: MD>
MD>int count;
MD>if (ERROR_SUCCESS != RegQueryValue(count)) // не забыли проверить возвращаемое значение
MD> break; // return, continue, throw, etc - короче, включаем мозги по ситуации
MD>for (int i = 0 ; i < count ; i++) // и не приплыли - цикл повторяется предсказуемое количество раз
MD>
К сожалению, не все таки умные.
В своё оправдание могу сказать только то, что я это не писал, оно мне досталось.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, skeptic, Вы писали:
S>>Обратная совместимость
AG>С чем? Кто-то рассчитывает прочитать определённый мусор?
Нет, просто где-то незначительно, где-то может и ощутимо просядет производительность у всего C++ кода, которого дофига. Непонятно, в чем проблема ввести требование обязательной инициализации?
Здравствуйте, Кодт, Вы писали:
К>Потому что функция в случае неудачи может К>- не инициализировать К>- инициализировать удобным дефолтным или сигнальным значением (0) К>- инициализировать неудобным сигнальным значением (-1 или 0xFFFFFFFF, или 0xDEADFACE какое-нибудь) К>- инициализировать случайным мусором
Инициализация не приведёт к желаемому результату только в последних двух случаях.
В WinAPI я таковых не встречал. В WinAPI чаще первый случай, хотя изредка второй.
В других API последние два тоже редкость.
И то, хоть инициализация и не поможет, дополнительного вреда она не принесёт.
К>Такая же логическая ошибка, только более регулярная: будет ходить не по разным граблям, а по одним и тем же.
Я за регулярность. Чтобы ошибка, которая вылезла только у меня, вылезла и у чувака, который это закоммитил.
AG>int count;
AG>RegQueryValue(&count); // забыли проверить возвращаемое значение
AG>for (int i = 0 ; i < count ; i++) // и приплыли - цикл повторяется непредсказуемое количество раз
AG>
Вероятно, вы имели ввиду выделенное.
AG>Почему не введут инициализацию для всех простых типов? AG>Для маньяков, которые не желают "платить за то, что не используют", можно же ввести синтаксис для "старой доброй русской рулетки". AG>Варианты, как это можно сделать: AG>
AG>int i = uninitialized; // "uninitialized" - не спец. значение, а magic, работающий только в инициализаторах, означающий, что мы хотим адреналина
AG>int i = void; // мы даже можем не вводить новый кейворд, если это так важно
AG>
Вы добавляете головной боли эмбеддед разработчикам. Не совсем понятно, что компилятор должен вставлять для случаев, связанных с регистрами железки, рассчитанными только на чтение, которые как-то мапятся на переменные. Или, например, для переменных из пространства ввода-вывода для процессоров с гарвардской архитектурой.
AG>
AG>[[uninitialized]]
AG>int i; // придумали аттрибуты, значит почему бы не использовать
AG>
То, что вы хотите, уже есть в эмбеддед, где существуют секции (сегменты), которые в известной степени позволяют прописывать правила размещения и инициализации переменных. Используются в сочетании с #pragma. И да, бывают случаи, когда глобальные переменные умышленно не инициализируются. Для того, например, чтобы информация была доступна после ресета процессора. В любом случае, момент инициализации досточно специфичен для каждого процессора и компилятора, чтобы быть легко стандартизированным.
AG>>int count;
AG>>RegQueryValue(&count); // забыли проверить возвращаемое значение
AG>>for (int i = 0 ; i < count ; i++) // и приплыли - цикл повторяется непредсказуемое количество раз
AG>>
Здравствуйте, Alexander G, Вы писали:
BFE>>Потому, что массивы бывают длинны. AG>Принимается. AG>Хотя я предложил и варианты эскейпа для явной не-инициализации, которые можно применить и к массивам.
Не надо этого. Ключи компиляции или прагмы какие тут лучше подойдут.
AG>>>RegQueryValue(count); // забыли проверить возвращаемое значение BFE>>А что собственно вы тут собрались проверять? AG>Это функция некоторого system API или legacy API, сообщающая результат через код возврата, который надо было бы проверить.
Договорится не использовать напрямую. Всегда через обертку:
int ApiRegQueryValue(int& err)
{
int count = 0;
err = RegQueryValue(count);
return count;
}
Здравствуйте, Alexander G, Вы писали:
AG>К сожалению, не все таки умные. AG>В своё оправдание могу сказать только то, что я это не писал, оно мне досталось.
Прекрасно понимаю — быть по колено в legacy часть нашей профессии. Но часть нашей профессиональной ответственности — выправлять если не архитектуру (ибо не всегда апрувят), то хоть такие мелкие залепухи, чтобы линейный код был устойчивым к жизни. Благо в большинстве компаний для таких фиксов не требуется благословления менеджмента.
Здравствуйте, visual_wind, Вы писали:
_>Вы добавляете головной боли эмбеддед разработчикам. Не совсем понятно, что компилятор должен вставлять для случаев, связанных с регистрами железки, рассчитанными только на чтение, которые как-то мапятся на переменные. Или, например, для переменных из пространства ввода-вывода для процессоров с гарвардской архитектурой.
Ну вообще-то регистры железа обычно объявляются как дефайны с адресом... А не как переменные, смапленные на память.
AG>>
AG>>[[uninitialized]]
AG>>int i; // придумали аттрибуты, значит почему бы не использовать
AG>>
_>То, что вы хотите, уже есть в эмбеддед, где существуют секции (сегменты), которые в известной степени позволяют прописывать правила размещения и инициализации переменных. Используются в сочетании с #pragma. И да, бывают случаи, когда глобальные переменные умышленно не инициализируются. Для того, например, чтобы информация была доступна после ресета процессора. В любом случае, момент инициализации досточно специфичен для каждого процессора и компилятора, чтобы быть легко стандартизированным.
Нету этого в эмбедед. Он пишет в частности про стековые переменные, как ты их собрался класть в секции?
Опять же, никто тебе не мешает и под десктопом переменные по секциям раскладывать...
Здравствуйте, enji, Вы писали:
E>Здравствуйте, visual_wind, Вы писали:
E>Ну вообще-то регистры железа обычно объявляются как дефайны с адресом... А не как переменные, смапленные на память.
Обычно в этом дефайне содержится разыменованный указатель на volatile int, к которому приведен этот самый адрес.
AG>>>[ccode] E>Нету этого в эмбедед. Он пишет в частности про стековые переменные, как ты их собрался класть в секции? E>Опять же, никто тебе не мешает и под десктопом переменные по секциям раскладывать...
Здесь да, согласен, я протупил. Увы, стековые переменные никак не проинициализируешь, положив их в секцию.
Здравствуйте, Alexander G, Вы писали:
AG>Ну вот какого хрена в век, когда лямбды уже не вызывают "это ты выпендрился?"-реакцию на код ревью, когда все самые необходимые смарт-поинтеры уже есть в std, а в boost есть вообще все нужные, до сих пор можно наткнуться на непредсказуемую инициализацию переменных?
AG>
AG>int count;
AG>RegQueryValue(count); // забыли проверить возвращаемое значение
AG>for (int i = 0 ; i < count ; i++) // и приплыли - цикл повторяется непредсказуемое количество раз
AG>
AG>Почему не введут инициализацию для всех простых типов?
Повторяя вслед за Кодтом, "потому что забытый ноль и.т.д.".
Это не решение проблемы. В данном конкретном случае нужно было просто завернуть вызов в функцию с контролем и выбросом исключения.
Нужно просто правильно проектировать интерфейсы. Если используются старые библиотеки или системное API, то следует использовать их не напрямую, а через
облагораживающие прокладки.
Здравствуйте, Alexander G, Вы писали:
AG>Я привёл выше синтаксис как до них добраться, вот другой синтаксис: AG>
AG>template<class T>
AG>void InitializeDefault()
AG>{
AG> T t = T(); // для чисел - 0, для bool - false, для указателей - nullptr, для классов - дефолтный конструктор.
AG> // на большинстве платформ двоичное представление этих значений - все байты нули.
AG>}
AG>
Для перечислений что будет?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Alexander G, Вы писали:
AG>for (int i = 0 ; i < count ; i++) // и приплыли — цикл повторяется непредсказуемое количество раз
Никуда я не приплыл
void RegQueryValue(int count)
{
}
int _tmain(int argc, _TCHAR* argv[])
{
int count;
RegQueryValue(count); // забыли проверить возвращаемое значениеfor (int i = 0 ; i < count ; i++) // и вот здесь выдается окно Run-Time Check Failure #3 - The variable 'count' is being used without being initialized.return 0;
}
Здравствуйте, Alexander G, Вы писали:
AG>Почему не введут инициализацию для всех простых типов?
предвижу такую проблему -- после того как это введут в стандарт и выйдут компиляторы это поддерживающие, народ перестанет иницилизировать переменные, а старые компиляторы останутся и начнется реальная непредсказуемость.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Здравствуйте, Alexander G, Вы писали:
AG>Ну вот как
AG>Почему не введут инициализацию для всех простых типов?
AG>Для маньяков, которые не желают "платить за то, что не используют", можно же ввести синтаксис для "старой доброй русской рулетки". AG>Варианты, как это можно сделать:
мне кажется, ближе к С++ будет что-то такое:
auto i = unitialized<int>
ну и заодно, я предлагаю убрать наконец auto и const (сделав их модификаторами по умолчанию), а для того, чтобы избежать путаницы между объявлением новой переменной и заменой старой, ввести слово change. Ну и добавить нормальный кортежи, типа
(i, b) = ShittyFuncWhichReturnsIntAndBool();
Зачем это нужно? Просто именно код, состоящий исключительно из объявлений новых констант, вычисляемых из старых, вызывает у меня наибольшее эстетическое удовольствие.