在Win32API编程中,通常使用带有多个字段的Cstruct.通常只有几个参数具有有意义的值,其他所有参数都必须清零.这可以通过以下两种方式中的任何一种来实现:

STRUCT theStruct;
memset( &theStruct, 0, sizeof( STRUCT ) );

STRUCT theStruct = {};

The second variant looks cleaner - it's a one-liner, it doesn't have any parameters that could be mistyped and lead to an err或 being planted.

与第一个版本相比,它有什么缺点吗?使用哪种变体以及原因?

推荐答案

这两个概念的含义不同.第一个使用memset函数,其目的是set a buffer of memory to certain value.第二个是initialize an object.让我用一些代码来解释一下:

假设您有一个包含成员only of POD types的 struct ("纯旧数据"-参见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的情况下,alignment字节被设置为零值.因为你不能正常访问这些字节,所以对你来说没有区别.

另一方面,既然你已经把你的问题标记为C++,我们来试试另一个例子,成员types different from 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的对象,因为它是我们 struct 的成员.接下来,memset将对象b所在的存储器设置为特定值,例如为零.现在,一旦我们的TestStruct对象超出范围,它将被销毁,当轮到它的成员std::string b时,你会看到崩溃,因为该对象的所有内部 struct 都被memset摧毁了.

所以,现实是,those things are very different,虽然在某些情况下,你有时需要将整个 struct 从memset变为零,但确保你明白你在做什么,而不是像我们的第二个例子那样犯错误,这一点总是很重要的.

我的投票-如果需要,在对象only上使用memset,在所有其他情况下使用default初始化x = {}.

C++相关问答推荐

rSP堆栈指针在返回函数调用的值时有任何用途吗?

带双指针的2D数组

在C语言中使用scanf()时我无法理解的警告

C/SDL程序,渲染不使用我的渲染器

在 struct 中强制转换空指针

Linux不想运行编译后的文件

C在声明带有值的数组时,声明大小有用吗?

将uintptr_t添加到指针是否对称?

C指针概念分段故障

tick.q中的Kdb+键控表语法

如何编写一个for循环来计算C中各项的总和?

在C中创建任意类型的只读指针参数

C程序向服务器发送TCPRST

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

使用正则表达式获取字符串中标记的开始和结束

如何不断地用C读取文件?

在同一范围内对具有相同类型的变量执行的相同操作在同一C代码中花费的时间不同

If语句默认为true

如何为avr atmega32微控制器构建C代码,通过光电二极管捕获光强度并通过串行通信传输数据

C23 中是否有 __attribute__((nonnull)) 的等效项?