初始化对象时,{0}是什么意思?

时间:2020-03-06 14:19:33  来源:igfitidea点击:

当使用{0}初始化对象时,它是什么意思?我在任何地方都找不到对" {0}"的引用,并且由于花括号,Google搜索没有帮助。

示例代码:

SHELLEXECUTEINFO sexi = {0}; // what does this do?
sexi.cbSize = sizeof(SHELLEXECUTEINFO);
sexi.hwnd = NULL;
sexi.fMask = SEE_MASK_NOCLOSEPROCESS;
sexi.lpFile = lpFile.c_str();
sexi.lpParameters = args;
sexi.nShow = nShow;

if(ShellExecuteEx(&sexi))
{
    DWORD wait = WaitForSingleObject(sexi.hProcess, INFINITE);
    if(wait == WAIT_OBJECT_0)
        GetExitCodeProcess(sexi.hProcess, &returnCode);
}

没有它,以上代码将在运行时崩溃。

解决方案

这里发生的事情称为聚合初始化。这是ISO规范8.5.1节中汇总的(缩写)定义:

An aggregate is an array or a class with no user-declared constructors, no private or protected non-static data members, no base classes, and no virtual functions.

现在,使用" {0}"初始化这样的聚合基本上是将整个事情都" 0"的一个技巧。这是因为使用聚合初始化时,我们不必指定所有成员,并且规范要求所有未指定的成员都进行默认初始化,这意味着对于简单类型,应将其设置为" 0"。

这是规范中的相关报价:

If there are fewer initializers in the list than there are members in the
  aggregate, then each member not
  explicitly initialized shall be
  default-initialized.
  Example:

struct S { int a; char* b; int c; };
S ss = { 1, "asdf" };

  
  initializes ss.a with 1, ss.b with
  "asdf", and ss.c with the value of an
  expression of the form int(), that is,
  0.

我们可以在此处找到有关此主题的完整规范

自从我在c / c ++中工作以来已经有一段时间了,但是IIRC,同样的快捷方式也可以用于数组。

我也用它来初始化字符串。

char mytext[100] = {0};

要注意的一件事是,该技术不会将填充字节设置为零。例如:

struct foo
{
    char c;
    int  i;
};

foo a = {0};

与以下内容不同:

foo a;
memset(&a,0,sizeof(a));

在第一种情况下,c和i之间的填充字节未初始化。你为什么要在乎?好吧,如果要将这些数据保存到磁盘或者通过网络或者其他方式发送,则可能会遇到安全问题。

请注意,空的聚合初始值设定项也可以工作:

SHELLEXECUTEINFO sexi = {};
char mytext[100] = {};

回答为何ShellExecuteEx()崩溃的原因:SHELLEXECUTEINFO" sexi"结构具有许多成员,而我们只初始化其中一些成员。

例如,成员" sexi.lpDirectory"可能指向任何地方,但是" ShellExecuteEx()"仍会尝试使用它,因此我们将遇到内存访问冲突。

当我们包括该行时:

SHELLEXECUTEINFO sexi = {0};

在进行其余结构设置之前,我们要告诉编译器在初始化我们感兴趣的特定结构成员之前将所有结构成员清零。ShellExecuteEx()知道,如果sexi.lpDirectory为零,则应该忽略它。