Любые причины, чтобы предпочесть memset/ZeroMemory значение инициализации для WinAPI-структур?

В программировании Win32 используется несколько структур POD. Эти структуры часто необходимо обнулить перед использованием.

Это можно сделать, позвонив memset()/ZeroMemory()

STRUCT theStruct;
ZeroMemory( &theStruct, sizeof( theStruct ) );

или инициализацией значения:

STRUCT theStruct = {};

Хотя два варианта выше не эквивалентны вообще:

  • относиться к дополнению иначе
  • обрабатывать переменные-члены не-POD по-разному

в случае структур POD, используемых в Win32, они выглядят эквивалентными.

Есть ли случаи, когда memset()/ZeroMemory() следует использовать вместо инициализации значения с помощью структур Win32 POD?

Ответ 1

Я всегда использую:

STRUCT theStruct = {}; // for C++, in C use {0}

Он короче, стандартен, поэтому более изящный, и мне все равно не нужны теоретические различия. Здесь мы говорим о коде для конкретной ОС.

Еще одно преимущество - вы также можете сразу установить размер структуры в первом члене следующим образом:

STRUCT theStruct = {sizeof(STRUCT)}; 

Многие структуры Win32 требуют, чтобы вы задавали размер в первом члене.

Ответ 2

В Win32, ZeroMemory - это всего лишь макрос вокруг RtlZeroRemory, который является макросом для memset. Поэтому я не думаю, что это имеет значение.

WinBase.h:

\#define ZeroMemory RtlZeroMemory"

WinNT.h:

\#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))

Ответ 3

Если ваш код послужит примером для бесчисленных разработчиков Visual Basic, которые, вероятно, не заметят или не поймут конструкцию С++ = {}, ZeroMemory - хороший способ сделать код С++ более похожим на псевдокод и минимизировать частоту тонкие, исправления ошибок инициализации волос.

Что беспокоит, что авторы статей MSDN столкнулись с, что затем объясняет, почему ZeroMemory появляется во множестве кода (даже кода на С++).

С другой стороны, если целью вашего кода на С++ является создание рабочего продукта, а не обучение всему миру, использование элегантной и выразительной силы языка С++ - отличная идея.

Ответ 4

Единственная причина, которую я могу предвидеть, чтобы не использовать инициализацию значения для "обнуления", это если у вас есть специальные версии memset/ZeroMemory (например, на основе SSE), или вам нужно избегать проблем с компилятором (ссылка на MSVC здесь, как и VS2008 memset, никогда не станет внутренним, но с некоторым умным кодированием (не используя asm) вы можете заставить внутреннюю (REP STOS))

Ответ 5

Единственная причина, по которой предпочтение memset/ZeroMemory для такого типа инициализации заключается в том, что функции WinAPI требуют/ожидают, что память будет инициализирована таким образом, то есть если функции WinAPI ожидают, что их нули будут физическими нулями - значения со всеми -zero бит.

Имейте в виду, что разница между представлением нулевого значения какого-либо типа и физического шаблона с нулевым битом зависит от реализации компилятора, а не от ОС. Теоретически компилятор Windows может использовать ненулевые битовые шаблоны для представления нулевых значений различных типов. Например, нулевой указатель может быть представлен ненулевым физическим значением в некотором воображаемом компиляторе C или С++ для Windows. (Не то, чтобы кто-нибудь действительно сделал это, конечно).

Ответ 6

Конечный результат одинаков (пока вы предполагаете, что 0 всегда представляется нулевыми битами), поэтому он в значительной степени вопрос стиля. Лично я предпочитаю инициализацию значения, поскольку он проще и не требует вызовов функций.

Кстати, вы должны инициализировать хотя бы одного участника:

STRUCT theStruct = {0};

Опускание 0 допускается некоторыми компиляторами C, но не стандартом C. С++ допускает упущение, но я предпочитаю всегда использовать 0.

Ответ 7

в С++ 11:

struct A {
    int x = 10;
    int y = 100;
    int z = 0;
};

старый стиль С++

struct A {
    int x;
    int y;
    int z;
    A() : x( 10 ), y( 100 ), z( 0 ) {} //constructor
};