Любая причина предпочесть 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
};