Здравствуйте, Павел Кузнецов, Вы писали:
ПК>От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?
Немного отвлекся от темы. Даже не ожидал, что тут такая дискуссия развернется
Хоть я и не говорил явно про "низкоуровневое обнуление", я имел в виду именно его. Предполагать, что такой подход будет использоваться для инициализации всех структур — это просто глупо.
Единственное применение для него (по крайней мере, в моих прогах) — это обнуление структур WinAPI (для того же используют обычно и ZeroMemory). В WinAPI очень много структур с кучей полей, и все они относятся к POD, поэтому применение такого подхода вполне правомерно, ИМХО. В любом случае — это намного лучше, чем инициализация случайными значениями. Забыл про одно поле — и всё, получил прогу с непредсказуемым поведением. Ищи потом, где что неправильно.
Написать же конструкторы в данном случае невозможно по вполне понятным причинам , и по этим же причинам можно не опасаться, что там появятся поля не-POD типов.
Здравствуйте, Mr. None, Вы писали:
MN>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое. MN>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
Что-то я не понял логики.
В любом случае, при использовании {0} компилятор заполнит все члены структуры нулевыми значениями, а не заполнит память нулями. Иными словами, если нулевой указатель в данной реализации представлен 0xFFFFFFFF, то компилятор обязан для всех указателей в структуре поместить именно это значение. Если там находится float и у него почему-то 0 представлен не-нулевым набором битов, компилятор должен поместить туда валидное представление нулевого значения. Бестиповый "0", читаем Страуструпа.
А вот ZeroMemory или memset ничего такого гарантировать не могут.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Лечение насморка отрубанием головы: зачем использовать кучу там, где можно обойтись выделением памяти "в стеке"?
Ну, может потребоваться, если блок чересчур велик для стека.
Здравствуйте, achp, Вы писали:
Д>>А вот ZeroMemory или memset ничего такого гарантировать не могут. A>Как это ничего? Они гарантируют, что нетипизированная область памяти (или массив объектов типа [un]signed] char) будет обнулена.
Дарней говорит про ЛОГИЧЕСКОЕ обнуление, а не физическое...
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
"Павел Кузнецов" <5834@news.rsdn.ru> wrote in message news:684083@news.rsdn.ru...
> >> Я что-то ни одного не припомню, чтобы memset работал, а = { 0 } — нет. > > > Такое может случиться при инициализации объединений, первые члены которых имеют, например, плавающие типы. > > Только в таком случае возникает вопрос: а какой из двух вариантов считать работающим? Кроме того, на платформе, где 0.0 или 0.0f представляется чем-то, отличным от последовательности нулевых байтов, memset для плавающих типов все равно использовать нельзя...
Считать работающим можно любой код вообще. Часто так и делают.
Оба варианта инициализации могут не работать. Все зависит от логики работы с инициализируемым объектом.
Для абстрактных данных в Си я предлагал следующее.
> ПК>От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?
> <...> Хоть я и не говорил явно про "низкоуровневое обнуление", я имел в виду именно его.
Ок. Если нужно побайтное обнуление — нужно использовать ZeroMemory/memset. Инициализация вида = { 0 } этого гарантировать не может. И наоборот, если нужна почленная инициализация значениями по умолчанию ("логический" 0) — нужно использовать что-нибудь из серии:
Struct s = { 0 };
Struct s = Struct();
и т.п.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, WolfHound, Вы писали:
Д>>>А вот ZeroMemory или memset ничего такого гарантировать не могут. A>>Как это ничего? Они гарантируют, что нетипизированная область памяти (или массив объектов типа [un]signed] char) будет обнулена. WH>Дарней говорит про ЛОГИЧЕСКОЕ обнуление, а не физическое...
Ага, я, читая его сообщение, проглядел слово "такого".
Здравствуйте, Павел Кузнецов, Вы писали:
>> Д> WNDCLASSEX wcx = { 0 };
>> а если нужно будет обнуль структурку потом,
ПК>
ПК>wcx = WNDCLASSEX();
ПК>
Тут ведь вот какая закавыка.
Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет". Но дело в том, что есть некомплиантые, но вполне еще используемые реализации компиляторов С++, где этого не делается.
Как-то привык все обнулять почленно/конструктором/мемсетом... Обязательно посмотрю, что бывает со структурой, инициализированной {0} в таком компиляторе.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ок. Если нужно побайтное обнуление — нужно использовать ZeroMemory/memset. Инициализация вида = { 0 } этого гарантировать не может. И наоборот, если нужна почленная инициализация значениями по умолчанию ("логический" 0) — нужно использовать что-нибудь из серии:
угу, для меня многое прояснилось.
Вроде бы такая простая вещь, а столько сложностей, оказывается
Здравствуйте, Аноним, Вы писали:
>>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все! ПК>>И каков смысл такого "обнуления"? А>Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!
Как-то встретился мне подобный код. Большой класс, в нем много переменных встроенных типов. Очень уж неохота было кому-то инициализировать каждую переменную по отдельности. И написал он такое:
some_class::some_class() {
ZeroMemory( this, sizeof( this ) );
}
Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...
Здравствуйте, alexkro, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
>>>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все! ПК>>>И каков смысл такого "обнуления"? А>>Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!
A>Как-то встретился мне подобный код. Большой класс, в нем много переменных встроенных типов. Очень уж неохота было кому-то инициализировать каждую переменную по отдельности. И написал он такое: A>
A>some_class::some_class() {
A> ZeroMemory( this, sizeof( this ) );
A>}
A>
A>Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...
X>Тут ведь вот какая закавыка. X>Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет".
Не "деволтный конструктор их обнуляет", а выполняется инициализация по умолчанию, которая сводится к обнулению. Конструкторы тут в большинстве случаев ни при чем. Тем более, что у некоторых POD-типов вообще нет никаких конструкторов.
Здравствуйте, alexkro, Вы писали:
A>Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...
Здравствуйте, Дарней, Вы писали:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д> WNDCLASSEX wcx = { 0 };
Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
ZeroMemory — незаменимая вещь, если одна из структур наследует другую.
Т.е. бывает, что хочется расширить существующую структуру из POD элементов.
Можно написать копию + свои элементы, а можно наследоваться.
Если работать с C++, то "правильней", IMHO, это наследование.
После этого к расширенной таким образом структуре нельзя применять = {0}.
Во всех случаях, кроме вышеуказанного, я использую ={0}.
MShura:
> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...> > После этого к расширенной таким образом структуре нельзя применять = {0}.
Есть три варианта кошерного "обнуления":
1) Не наследовать свою структуру, а включить в нее другую. В этом случае можно использовать = { 0 }.
2) Наследовать, но "обнулять" так:
MyStruct s = MyStruct();
3) Предоставить в унаследованной структуре конструктор, в котором и "обнулять" базовую структуру.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Андрей Тарасевич, Вы писали:
X>>Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет".
АТ>Не "деволтный конструктор их обнуляет", а выполняется инициализация по умолчанию, которая сводится к обнулению. Конструкторы тут в большинстве случаев ни при чем.
Да, незавимо от корректности построения фраз, выяснилось, что, даже в случае компилятора, который не выполняет иницализацию по умолчанию для POD типов, ={0} "обнуляет" (ну то есть выполняет инициализацию по умочанию) для входящих в структуру полей. И отказывается компилировать, если одно из полей или сама структура имеет конструктор.
АТ>Тем более, что у некоторых POD-типов вообще нет никаких конструкторов.
А что тогда для них вызывает какой-нибудь std::vector при вызове vector::vector(size_type)?
>> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...> >> После этого к расширенной таким образом структуре нельзя применять = {0}.
ПК>Есть три варианта кошерного "обнуления":
ПК>2) Наследовать, но "обнулять" так: ПК>
ПК>MyStruct s = MyStruct();
ПК>
Не знаю что говорят об этом стандарты, но практика говорит, что ни VC6, ни VC7, ни gcc 3.2.2, ни Watcom 11 таким образом не "обнулят" структуру это точно.