在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 = {}

10-07 18:53
查看更多