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

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

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

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

или по инициализации значения:

STRUCT theStruct = {};

хотя два варианта выше не эквивалентны в целом:

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

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

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

7 ответов


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

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

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

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

STRUCT theStruct = {sizeof(STRUCT)}; 

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


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

WinBase.h:

\#define ZeroMemory RtlZeroMemory"

WinNT.h:

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

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

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

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


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


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

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


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

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

STRUCT theStruct = {0};

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


в C++11:

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

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

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