通常,数据结构的有效初始化是将所有成员设置为零.即使使用C++进行编程,也可能需要与外部API进行交互.
以下是否有任何实际区别:
some_struct s;
memset(&s, 0, sizeof(s));
Run Code Online (Sandbox Code Playgroud)
简单地说
some_struct s = { 0 };
Run Code Online (Sandbox Code Playgroud)
人们发现自己都使用这两种方法,选择哪种方法更适合给定的应用程序?(希望据了解,这只适用于POD结构;如果该结构中存在C++ std :: string,则会遇到各种各样的破坏.)
对于我自己来说,作为一个不使用memset的C++程序员,我从不确定函数签名,所以我发现第二个例子更容易使用,除了更少打字,更紧凑,甚至更多很明显,因为它在声明中说"这个对象被初始化为零"而不是等待下一行代码并且看到"哦,这个对象初始化为零".
在C++中创建类和结构时,我倾向于使用初始化列表; 我很好奇人们对上面两个"C风格"初始化的想法,而不是与C++中可用的内容进行比较,因为我怀疑我们很多人都与C库接口,即使我们自己主要用C++编写代码.
编辑: Neil Butterworth 在后续提出这个问题,我认为这是这个问题的一个有趣的推论.
AnT*_*AnT 23
memset实际上从来都不是正确的方法.是的,存在实际差异(见下文).
在C++中,不是所有东西都可以用文字初始化0(枚举类型的对象不能),这就是为什么在C++中常见的习语是
some_struct s = {};
Run Code Online (Sandbox Code Playgroud)
而在C语言中,成语是
some_struct s = { 0 };
Run Code Online (Sandbox Code Playgroud)
注意,在C = { 0 }中,可以称为 通用零初始化器.它可以与几乎任何类型的对象一起使用,因为{}-enclosed初始化器也允许使用标量对象
int x = { 0 }; /* legal in C (and in C++) */
Run Code Online (Sandbox Code Playgroud)
这使得= { 0 }在通用类型无关的C代码(例如,与类型无关的宏)中有用.
= { 0 }C89/90和C++ 中初始化程序的缺点是它只能用作声明的一部分.(C99通过引入固定这个问题复合文字.类似的功能即将C++为好.)由于这个原因,你可能会看到许多程序员使用memset以零出来的东西在C89/90或C++代码的中间.然而,我会说正确的做法仍然没有memset,而是有类似的东西
some_struct s;
...
{
const some_struct ZERO = { 0 };
s = ZERO;
}
...
Run Code Online (Sandbox Code Playgroud)
即通过在代码中间引入"虚构"块,即使它在第一眼看上去看起来不太漂亮.当然,在C++中没有必要引入块.
至于实际差异......你可能会听到有些人说memset在实践中会产生相同的结果,因为实际上物理的全零位模式是用来表示所有类型的零值.但是,这通常不是真的.一个能够证明典型C++实现差异的直接示例是指向数据成员的指针类型
struct S;
...
int S::*p = { 0 };
assert(p == NULL); // this assertion is guaranteed to hold
memset(&p, 0, sizeof p);
assert(p == NULL); // this assertion will normally fail
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为典型的实现通常使用全一位模式(0xFFFF...)来表示此类型的空指针.上面的例子演示了归零memset和普通= { 0 }初始化器之间的实际实际差异.
Mar*_*som 15
some_struct s = { 0 };保证工作; memset依赖于实施细节,最好避免.
如果struct包含指针,则所产生的所有位0的值memset可能与0在C(或C++)代码中指定它的意义不同,即NULL指针.
(这也可能是与案件floats和doubles,但是,我从来没有遇到过.不过,我不认为标准保证了他们能够成为零memset无论是.)
编辑:从一个更务实的角度来看,我仍然会说memset尽可能避免使用,因为它是一个额外的函数调用,写入时间更长,并且(在我看来)意图不太明确= { 0 }.