Здравствуйте, B0FEE664, Вы писали:
BFE>Потому, что массивы бывают длинны.
Можно ввести понятие "статический массив размера N, у которого имеют смысл только первые M членов".
N — определяется при создании массива и меняться при его жизни не может. К сожалению, оно пока что в С++ может существовать лишь как константа времени компиляции, ведь alloca — некроссплатформенная хрень.
M — может меняться со временем.
Попытки обратиться к членам, находящимся за M-ым, пресекаются ассертом.
Так вот, массивы можно по умолчанию инициализировать как "изначально M=0". Если надо считать в массив информацию — то по одному наращиваем M, добавляя в конец конкретное значение.
Если надо сразу резко увеличить M — то тогда все новые элементы либо заполняются заранее оределённым значением, либо для них вызывается конструктор по умолчанию.
AG>>>RegQueryValue(&count); // забыли проверить возвращаемое значение
AG>>>
AG>Забыл указать, я о С++, а не о С. AG>Это — ссылка.
Если таки RegQueryValue -- это не С-шная апишная функция, а таки С++ обёртка, то просто её надо было писать по-человечески, а не на компилятор пенять.
Например оно могло бы быть примерно таким:
int RegQueryValue( int& errCode, int defaultValue = 0 );
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Если таки RegQueryValue -- это не С-шная апишная функция, а таки С++ обёртка, то просто её надо было писать по-человечески, а не на компилятор пенять. E>Например оно могло бы быть примерно таким:
int RegQueryValue( int& errCode, int defaultValue = 0 );
Зело убого смотрится, не согласен.
В таких случаях нужно исключение бросать, его проигнорировать невозможно. К тому же вылететь по не пойманному исключению намного лучше, чем посчитать погоду в африке.
В BCL очень грамотно подошли к этому вопросу: названия тех методов, которые не бросают исключение начинается Try, например: Double.TryParse() не бросает, а Double.Parse().
ЗЫ: За игнорирование возвращаемых значений нужно бить по рукам, желательно автоматически. Если уж хочется проигнорировать, то нужен способ сделать это явно (например, подавить варнинг директивой).
Всё сказанное выше — личное мнение, если не указано обратное.
12/23/2013 12:33 AM, Философ пишет:
> Зело убого смотрится, не согласен. > В таких случаях нужно исключение бросать, его проигнорировать > невозможно.
Бред. Все определяется только задачей.
Здравствуйте, Философ, Вы писали:
Ф>Зело убого смотрится, не согласен. Ф>В таких случаях нужно исключение бросать, его проигнорировать невозможно. К тому же вылететь по не пойманному исключению намного лучше, чем посчитать погоду в африке.
Это очень зависит от всего на свете. Например от кдинг стайла принятого в команде. Исключения вообще не везде разрешены, даже, ну и потом, даже там, где разрешены, их не обязательно можно будет бросать из этой функции...
Обычно таки исключения -- это исключительная ситуация же. Ну, например, не работает риестр вообще, или там,, нет доступа к нужной переменной.
А вот ситуация, что ключа просто нет, не задан, вполне может быть и штатной...
Кстати, исключение проигнорировать так же просто, как и специально заведённую для кода ошибки переменную...
Ф>В BCL очень грамотно подошли к этому вопросу: названия тех методов, которые не бросают исключение начинается Try, например: Double.TryParse() не бросает, а Double.Parse().
Есть разные соглашения и подходы к тому, как и для чего надо использовать исключения.
Я, например, сторонник их использования, но только для реально исключительных ситуаций...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Alexander G, Вы писали:
AG>Нет, я хочу, чтобы просто
Скажите, а вот:
struct megabyte_t {
char i[1048576];
};
int
foo(void)
{
struct megabyte_t x;
... /* lot of code here */
}
Вы как хотите чтобы компилилось?
То есть вы реально готовы пойти на скрытый оверхед в инициализации мегабайтной переменной на стеке нулями просто вот так на пустом месте? Я полагаю, ваше скромное предложение, формально обратно совместимое, реально поломает обратную совместимость в том смысле, что весь код написанный в old-style все равно придется переписывать на =undefined из-за немыслимых просадок по перфомансу в легаси.
Но это ещё ладно. А теперь представьте у вас хитрый и стрёмный volatile вот такого вида:
extern volatile int port_b; // это не переменная, это порт ввода-вывода
// чтение -- состояние боевого лазера
// запись команды: port_b = 1; -- уничтожение флота пришельцев
// port_b = 2; -- самоуничтожение
// port_b = 0; -- уничтожение планеты Земля
Вы точно хотите дефолтно инициализировать её нулём? Не предупреждая разработчиков?
+1 Для многих объектов (в том числе встроенных типов) вполне хорошо и привычно находиться в частично инициализированном состоянии, в котором ему либо что-то будет присвоено, либо он будет разрушен. Я с этим смирился, а некоторые видимо нет .
Здравствуйте, skeptic, Вы писали:
S>Здравствуйте, Alexander G, Вы писали:
AG>>Здравствуйте, skeptic, Вы писали:
S>>>Какой предсказуемостью? Как ты узнаешь что 0 это неинициализированная переменная а не кто то присвоил 0?
AG>>С реализацией такого предложения будет не важно, присвоил ли кто-то 0, или оно там само.
AG>>Предсказуемость в том, что даже если 0 там не есть то, что хотели, ошибочное поведение будет стабильным, а не зависеть от конфигурации, компилятора, ОС, и того, какая функция вызывалась на этом стеке раньше.
S>Ну, по спец.синтаксису я резко против, по понятным причинам — поломается много кода. S>А по дефолтному присваиванию я думаю это не решит проблемы, зато добавит их разработчикам стандарта и компиляторов. S>Ну и всё таки не ясно как выбирать дефолтные значения для разных типов?
А в чем проблема с дефолтными значениями? Во всяких там джавах именно так и делают — инициализируют все переменные по умолчанию.
Здравствуйте, Alexander G, Вы писали:
AG>Ну вот какого хрена в век, когда лямбды уже не вызывают "это ты выпендрился?"-реакцию на код ревью, когда все самые необходимые смарт-поинтеры уже есть в std, а в boost есть вообще все нужные, до сих пор можно наткнуться на непредсказуемую инициализацию переменных?
AG>
AG>int count;
AG>RegQueryValue(count); // забыли проверить возвращаемое значение
AG>for (int i = 0 ; i < count ; i++) // и приплыли - цикл повторяется непредсказуемое количество раз
AG>
Приучи себя к простейшим правилам написания безопасного кода, и подобные проблемы отпадут сами собой.