在Win32 API编程中,通常将C struct
与多个字段一起使用。通常,其中只有几个具有有意义的值,而所有其他值都必须归零。这可以通过以下两种方式之一来实现:
STRUCT theStruct;
memset( &theStruct, 0, sizeof( STRUCT ) );
要么
STRUCT theStruct = {};
第二个变体看起来更干净-它是单线的,它没有任何可能被错误键入并导致植入错误的参数。
与第一个变体相比,它有什么缺点吗?使用哪个变体,为什么?
最佳答案
这两个结构在含义上有很大不同。第一个使用memset
函数,该函数旨在将内存缓冲区设置为特定值。第二个初始化一个对象。让我用一些代码来解释一下:
假设您有一个仅包含POD类型成员的结构(“普通旧数据”-请参见What are POD types in C++?)
struct POD_OnlyStruct
{
int a;
char b;
};
POD_OnlyStruct t = {}; // OK
POD_OnlyStruct t;
memset(&t, 0, sizeof t); // OK as well
在这种情况下,编写POD_OnlyStruct t = {}
或POD_OnlyStruct t; memset(&t, 0, sizeof t)
并没有多大区别,因为我们唯一的区别是在使用memset
的情况下将对齐字节设置为零值。由于您通常无法访问这些字节,因此没有任何区别。另一方面,由于您已将问题标记为C++,因此让我们尝试另一个示例,其成员类型不同于POD:
struct TestStruct
{
int a;
std::string b;
};
TestStruct t = {}; // OK
{
TestStruct t1;
memset(&t1, 0, sizeof t1); // ruins member 'b' of our struct
} // Application crashes here
在这种情况下,使用像TestStruct t = {}
这样的表达式会很好,并且在其上使用memset
会导致崩溃。如果使用memset
,则会发生以下情况-创建了TestStruct
类型的对象,因此创建了std::string
类型的对象,因为它是我们结构的成员。接下来,memset
将对象b
所在的内存设置为某个值,例如零。现在,一旦我们的TestStruct对象超出范围,它将被销毁,当轮到它的成员std::string b
时,您将看到崩溃,因为memset
破坏了该对象的所有内部结构。因此,实际情况是,这些事情有很大的不同,尽管有时在某些情况下您有时需要将整个结构
memset
编码为零,但确保您了解自己在做什么,而不是像在我们的工作中犯错一样,始终非常重要。第二个例子。我的投票-仅在需要时才在对象上使用
memset
,并在所有其他情况下使用默认的初始化x = {}
。