C++ 初始化对象时 {0} 是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/88957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does {0} mean when initializing an object?
提问by Mahmoud Al-Qudsi
When {0}
is used to initialize an object, what does it mean? I can't find any references to {0}
anywhere, and because of the curly braces Google searches are not helpful.
什么时候{0}
用来初始化一个对象,是什么意思?我找不到任何对{0}
任何地方的引用,而且由于花括号,谷歌搜索没有帮助。
Example code:
示例代码:
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);
}
Without it, the above code will crash on runtime.
没有它,上面的代码将在运行时崩溃。
回答by Don Neufeld
What's happening here is called aggregateinitialization. Here is the (abbreviated) definition of an aggregate from section 8.5.1 of the ISO spec:
这里发生的事情称为聚合初始化。以下是 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.
聚合是没有用户声明的构造函数、没有私有或受保护的非静态数据成员、没有基类和虚函数的数组或类。
Now, using {0}
to initialize an aggregate like this is basically a trick to 0
the entire thing. This is because when using aggregate initialization you don't have to specify all the membersand the spec requires that all unspecified members be default initialized, which means set to 0
for simple types.
现在,使用{0}
像这样初始化聚合基本上是0
整个事情的一个技巧。这是因为在使用聚合初始化时,您不必指定所有成员,并且规范要求所有未指定的成员都默认初始化,这意味着0
为简单类型设置为。
Here is the relevant quote from the spec:
这是规范中的相关引用:
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
with1
,ss.b
with"asdf"
, andss.c
with the value of an expression of the formint()
, that is,0
.
如果列表中的初始值设定项少于聚合中的成员数,则每个未显式初始化的成员都应默认初始化。例子:
struct S { int a; char* b; int c; }; S ss = { 1, "asdf" };
ss.a
用1
、ss.b
用"asdf"
和ss.c
形式的表达式的值初始化int()
,即0
。
You can find the complete spec on this topic here
您可以在此处找到有关此主题的完整规范
回答by Harold Ekstrom
One thing to be aware of is that this technique will not set padding bytes to zero. For example:
需要注意的一件事是这种技术不会将填充字节设置为零。例如:
struct foo
{
char c;
int i;
};
foo a = {0};
Is not the same as:
不等同于:
foo a;
memset(&a,0,sizeof(a));
In the first case, pad bytes between c and i are uninitialized. Why would you care? Well, if you're saving this data to disk or sending it over a network or whatever, you could have a security issue.
在第一种情况下, c 和 i 之间的填充字节未初始化。你为什么会在意?好吧,如果您将此数据保存到磁盘或通过网络或其他方式发送它,您可能会遇到安全问题。
回答by dalle
Note that an empty aggregate initializer also works:
请注意,空聚合初始值设定项也有效:
SHELLEXECUTEINFO sexi = {};
char mytext[100] = {};
回答by snowcrash09
In answer to why ShellExecuteEx()
is crashing: your SHELLEXECUTEINFO
"sexi" struct has many members and you're only initializing some of them.
回答为什么ShellExecuteEx()
会崩溃:您的SHELLEXECUTEINFO
“sexi”结构有很多成员,而您只初始化了其中的一些。
For example, the member sexi.lpDirectory
could be pointing anywhere, but ShellExecuteEx()
will still try to use it, hence you'll get a memory access violation.
例如,该成员sexi.lpDirectory
可能指向任何地方,但ShellExecuteEx()
仍会尝试使用它,因此您会遇到内存访问冲突。
When you include the line:
当您包含该行时:
SHELLEXECUTEINFO sexi = {0};
before the rest of your structure setup, you're telling the compiler to zero out allstructure members before you initialize the specific ones you're interested in. ShellExecuteEx()
knows that if sexi.lpDirectory
is zero, it should ignore it.
在你的结构设置的其余部分之前,你告诉编译器在初始化你感兴趣的特定成员之前将所有结构成员归零。ShellExecuteEx()
知道如果sexi.lpDirectory
为零,它应该忽略它。
回答by Adam Pierce
I also use it to initialize strings eg.
我也用它来初始化字符串,例如。
char mytext[100] = {0};
回答by Keith Thompson
{0}
is a valid initializer for any (complete object) type, in both C and C++. It's a common idiom used to initialize an object to zero(read on to see what that means).
{0}
是 C 和 C++ 中任何(完整对象)类型的有效初始值设定项。这是用于将对象初始化为零的常用习惯用法(请继续阅读以了解这意味着什么)。
For scalar types (arithmetic and pointer types), the braces are unnecessary, but they're explicitly allowed. Quoting the N1570 draftof the ISO C standard, section 6.7.9:
对于标量类型(算术和指针类型),大括号是不必要的,但它们是明确允许的。引用ISO C 标准的N1570 草案,第 6.7.9 节:
The initializer for a scalar shall be a single expression, optionally enclosed in braces.
标量的初始值设定项应为单个表达式,可选地括在大括号中。
It initializes the object to zero (0
for integers, 0.0
for floating-point, a null pointer for pointers).
它将对象初始化为零(0
对于整数,0.0
对于浮点数,对于指针,空指针)。
For non-scalar types (structures, arrays, unions), {0}
specifies that the firstelement of the object is initialized to zero. For structures containing structures, arrays of structures, and so on, this is applied recursively, so the first scalar element is set to the zero, as appropriate for the type. As in any initializer, any elements not specified are set to zero.
对于非标量类型(结构、数组、联合),{0}
指定对象的第一个元素初始化为零。对于包含结构、结构数组等的结构,这是递归应用的,因此第一个标量元素设置为零,与类型相适应。与任何初始化程序一样,任何未指定的元素都设置为零。
Intermediate braces ({
, }
) may be omitted; for example both these are valid and equivalent:
中间大括号 ( {
, }
) 可以省略;例如,这两个都是有效的和等效的:
int arr[2][2] = { { 1, 2 }, {3, 4} };
int arr[2][2] = { 1, 2, 3, 4 };
which is why you don't have to write, for example, { { 0 } }
for a type whose first element is non-scalar.
例如,这就是为什么您不必{ { 0 } }
为第一个元素是非标量的类型编写代码。
So this:
所以这:
some_type obj = { 0 };
is a shorthand way of initializing obj
to zero, meaning that each scalar sub-object of obj
is set to 0
if it's an integer, 0.0
if it's floating-point, or a null pointer if it's a pointer.
是初始化obj
为零的速记方式,这意味着如果它是整数,如果它是浮点数,或者如果它是一个指针,则每个标量子对象obj
被设置为空指针。0
0.0
The rules are similar for C++.
C++ 的规则类似。
In your particular case, since you're assigning values to sexi.cbSize
and so forth, it's clear that SHELLEXECUTEINFO
is a struct or class type (or possibly a union, but probably not), so not all of this applies, but as I said { 0 }
is a common idiom that can be used in more general situations.
在您的特定情况下,由于您正在为sexi.cbSize
等等分配值,很明显这SHELLEXECUTEINFO
是一个结构或类类型(或可能是联合,但可能不是),所以并非所有这些都适用,但正如我所说的{ 0 }
是一个常见的可以在更一般的情况下使用的习语。
This is not(necessarily) equivalent to using memset
to set the object's representation to all-bits-zero. Neither floating-point 0.0
nor a null pointer is necessarily represented as all-bits-zero, and a { 0 }
initializer doesn't necessarily set padding bytes to any particular value. On most systems, though, it's likely to have the same effect.
这并不(必然)等同于memset
用于将对象的表示设置为全位零。浮点0.0
和空指针都不一定表示为所有位为零,并且{ 0 }
初始化程序不一定将填充字节设置为任何特定值。但是,在大多数系统上,它可能具有相同的效果。
回答by μBio
It's been awhile since I worked in c/c++ but IIRC, the same shortcut can be used for arrays as well.
自从我在 c/c++ 中工作以来已经有一段时间了,但是 IIRC,同样的快捷方式也可以用于数组。
回答by Ingo Blackman
I have always wondered, whyyou should use something like
我一直想知道,为什么你应该使用类似的东西
struct foo bar = { 0 };
Here is a test case to explain:
下面是一个测试用例来解释:
check.c
检查.c
struct f {
int x;
char a;
} my_zero_struct;
int main(void)
{
return my_zero_struct.x;
}
I compile with gcc -O2 -o check check.c
and then output the symbol table with readelf -s check | sort -k 2
(this is with gcc 4.6.3 on ubuntu 12.04.2 on a x64 system). Excerpt:
我编译gcc -O2 -o check check.c
然后输出符号表readelf -s check | sort -k 2
(这是在 x64 系统上的 ubuntu 12.04.2 上使用 gcc 4.6.3)。摘抄:
59: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
48: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS _edata
25: 0000000000601018 0 SECTION LOCAL DEFAULT 25
33: 0000000000601018 1 OBJECT LOCAL DEFAULT 25 completed.6531
34: 0000000000601020 8 OBJECT LOCAL DEFAULT 25 dtor_idx.6533
62: 0000000000601028 8 OBJECT GLOBAL DEFAULT 25 my_zero_struct
57: 0000000000601030 0 NOTYPE GLOBAL DEFAULT ABS _end
The important part here is, that my_zero_struct
is after __bss_start
. The ".bss" section in a C program is the section of memory which is set to zero beforemain
is called see wikipedia on .bss.
这里的重要部分是,my_zero_struct
在__bss_start
. C 程序中的“.bss”部分是在调用之前设置为零的内存部分,main
请参阅.bss 上的维基百科。
If you change the code above to:
如果你把上面的代码改成:
} my_zero_struct = { 0 };
Then the resulting "check" executable looks exactlythe same at least with the gcc 4.6.3 compiler on ubuntu 12.04.2; the my_zero_struct
is still in the .bss
section and thus it will be automatically initialized to zero, before main
is called.
然后生成的“检查”可执行文件至少与 ubuntu 12.04.2 上的 gcc 4.6.3 编译器看起来完全相同;在my_zero_struct
仍处于.bss
部分,因此它会被自动初始化为零,之前main
被调用。
Hints in the comments, that a memset
might initialize the "full" structure is also not an improvement, because the .bss
section is cleared fully which also means the "full" structure is set to zero.
注释中的提示,memset
可能初始化“完整”结构也不是改进,因为该.bss
部分已完全清除,这也意味着“完整”结构设置为零。
It mightbe that the C language standard does not mention any of this, but in a real world C compiler I have never seen a different behaviour.
这可能是C语言标准并没有提及任何这一点,但在现实世界中的C编译器我从来没有见过一个不同的行为。
回答by nitin prajapati
{0} is an anonymous arraycontaining its element as 0.
{0} 是一个匿名数组,其元素为 0。
This is used to initialize one or all elements of array with 0.
这用于将数组的一个或所有元素初始化为 0。
e.g. int arr[8] = {0};
例如 int arr[8] = {0};
In this case all the elements of arr will be initialized as 0.
在这种情况下,arr 的所有元素都将被初始化为 0。