是否有理由更喜欢memset / ZeroMemory来为WinAPI结构初始化值?

时间:2010-10-04 07:27:35

标签: c++ c winapi struct initialization

在Win32编程中,使用了一些POD结构。这些结构通常需要在使用前清零。

可以通过致电memset() / ZeroMemory()

来完成
STRUCT theStruct;
ZeroMemory( &theStruct, sizeof( theStruct ) );

或通过值初始化:

STRUCT theStruct = {};

虽然the two variants above are not equivalent in general

  • 以不同方式处理填充
  • 以不同方式处理非POD成员变量

如果在Win32中使用POD结构,它们看起来是等效的。

是否应该使用memset() / ZeroMemory()而不是使用Win32 POD结构进行值初始化?

7 个答案:

答案 0 :(得分:23)

我总是使用:

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

它更短,更标准,因此更优雅,我并不真正关心理论差异。我们在这里讨论具体操作系统的代码。

另一个优点是你也可以立即在第一个成员中设置结构大小,如下所示:

STRUCT theStruct = {sizeof(STRUCT)}; 

许多Win32结构要求您在第一个成员中设置大小。

答案 1 :(得分:8)

在Win32中,ZeroMemory只是RtlZeroRemory周围的一个宏,它是memset的一个宏。所以,我认为它不会有所作为。

WinBase.h

\#define ZeroMemory RtlZeroMemory"

WinNT.h

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

答案 2 :(得分:4)

如果您的代码将作为无数可能不会注意或理解C ++ = {}构造的Visual Basic开发人员的示例,那么ZeroMemory是使C ++代码看起来更像伪代码并最小化的好方法。微妙的,头发撕裂初始化错误的发生率。

这就是MSDN article authors faced的问题,这就解释了为什么ZeroMemory会出现在如此多的代码中(甚至是C ++代码)。

另一方面,如果你的C ++代码的目的是制作一个有效的产品,而不是教导世界,那么使用C ++语言优雅而富有表现力的力量是一个好主意。

答案 3 :(得分:2)

唯一的原因(我可以预见)不使用值初始化'归零'是因为你有memset / ZeroMemory的特殊版本(例如基于SSE的版本),或者你需要避免编译器的问题(在这里指的是MSVC,从VS2008 memset永远不会成为内在的,但是通过一些聪明的编码(不使用asm)你可以强制内在的(REP STOS))

答案 4 :(得分:2)

首选memset / ZeroMemory进行此类初始化的唯一理由是,如果WinAPI函数要求/期望要以这种方式初始化内存,即WinAPI函数是否正常期望它们的零为物理零 - 具有全零位模式的值。

请记住,某种类型的零值表示与物理全零位模式之间的区别取决于编译器实现,而不是OS。理论上,Windows编译器可以使用非零位模式来表示各种类型的零值。就像,在一些虚构的C或C ++编译器中,空指针可能由非零物理值表示。 (当然,并不是说有人会这样做)。

答案 5 :(得分:1)

最终结果是相同的(只要你假设0 is always represented by all-zero-bits),所以它主要是风格问题。就个人而言,我更喜欢值初始化,因为它更简单,不需要函数调用。

顺便说一下,您必须至少初始化一个成员:

STRUCT theStruct = {0};

某些C编译器允许省略0,但C标准不允许。 C ++允许省略,但我更喜欢只使用0

答案 6 :(得分:-1)

在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
};