我和一位同事正在讨论将struct
归零的某些方法的效率。我们假设我们有一个简单的struct
,如此:
struct {
int iMyInt;
char cMyChar;
double dCoordinates[128];
} s_t;
我的方法是这样做:
s_t myStruct = { 0 };
我的同事改为采用这种方法:
s_t myStruct = { };
他注意到我的方法在两部分操作中初始化单个元素,然后初始化其余元素,而他的方法在一个部分操作中初始化整个struct
,这个操作更快更多高效。
这是真的,如果是这样的话,所有编译器优化级别的情况总是如此(即:编译器是否会解决这个问题并为我优化它?)
谢谢。
答案 0 :(得分:6)
首先,您发布的代码无效:您应该声明结构类型如下
struct s_t {
int iMyInt;
char cMyChar;
double dCoordinates[128];
};
那说:在你的具体情况下,两种方法是相同的,一切都是零。对于使用上述任何成员和/或数组元素的通用测试代码,-O3
甚至-O0
对于clang 没有差异(-O0
它甚至在两种情况下都会在整个结构上调用memset
。
s_t obj = {0};
movq %rcx, %rdi
movl %eax, %esi
callq memset
s_t obj = {};
movq %rcx, %rdi
movl %eax, %esi
callq memset
答案 1 :(得分:1)
C ++11§8.5.1/ 7:
“如果列表中的初始化子条款少于聚合中的成员,那么每个成员 未显式初始化应从空初始化列表
初始化
最后一点C ++11§8.5.4/ 3:
“否则[即。 T不是类,不是聚合,也不是引用],如果初始化列表没有元素,则对象是值初始化的。
对于像int
这样的简单类型初始化值意味着零初始化。
因此,对于具有{0}
值的类型,0
的正式效果与{}
的正式效果相同。
然而,标准不能规定编译器的实施质量。编译器可能会对文件名中的错误单词作出反应,并且只是在每次函数调用之前都会产生耗时的虚拟代码。同样地,它理论上可能会以不同的方式对待这两个符号。代码生成,即使它们的含义相同。
重温你同事的想法
“他注意到我的方法在两部分操作中初始化单个元素,然后初始化其余元素,而他的方法在单部分操作中初始化整个结构更快更有效。
不,这只是对编译器如何工作的错误观点。
编译器无法正常工作。
但空括号表示法的优点在于它也适用于例如std::string
以及T
其中T()
是有效表达式的任何其他类型T(0)
,但typedef struct Point_tag
{
int x, y;
} Point;
不是。
即。它略胜一筹。
所有这些都说明,在C ++中没有必要进行C杂技
struct Point
{
int x, y;
};
相反,你可以简单地做
{{1}}