int a[100] = {};
int a[100];
memset(a, 0, sizeof(a));
int a[100];
fill(a, a + 100, 0);
从上面显示的方法中将新数组归零的最佳方法是什么?它们之间有什么区别?
答案 0 :(得分:4)
1:最好的。它将所有值设置为默认值,大多数值为0。
2:这很危险,它会将模式0复制到整个数组中。例如,如果数组是浮点数,则无法保证它表示为零。 memset也会按字节顺序复制,而不是单词,如果你传递的不是零,会导致各种问题。例如,memset(a, 1, ...)
会使其填充16843009
。除非使用C字符串,否则不应使用Memset。
3:合法,清晰。易于扩展到非零值,而(1)则不会。虽然更冗长。
答案 1 :(得分:2)
决定使用VS2010进行全面优化来调查性能问题。
有趣的结果:
1:13105
2:13044
3:4546
没有初始化案例:906。
因此,VS2010在案例memset
中使用1
非常相似,但fill
的优化程度更高。
#include "stdafx.h"
#include <Windows.h>
#include <algorithm>
#include <iostream>
int fref()
{
int a[1024];
return a[512] - a[256];
}
int f1()
{
int a[1024] = {};
return a[512] - a[256];
}
int f2()
{
int a[1024];
memset(a, 0, sizeof(a));
return a[512] - a[256];
}
int f3()
{
int a[1024];
std::fill(a, a + 100, 0);
return a[512] - a[256];
}
typedef int (*Function)();
LONGLONG time(Function function)
{
const unsigned numLoops = 50000;
LARGE_INTEGER start;
QueryPerformanceCounter(&start);
for(unsigned j = 1; j != numLoops; ++j)
function();
LARGE_INTEGER end;
QueryPerformanceCounter(&end);
return end.QuadPart-start.QuadPart;
}
Function tests[]=
{
&fref, &f1, &f2, &f3
};
const unsigned numTests = sizeof(tests)/sizeof(tests[0]);
LONGLONG results[numTests] = {};
int _tmain(int argc, _TCHAR* argv[])
{
for(unsigned i = 0; i != numTests; ++i)
{
results[i] = time(tests[i]);
}
for(unsigned i = 0; i != numTests; ++i)
std::cout << results[i] << std::endl;
getchar();
return 0;
}
答案 2 :(得分:1)
使用Keith的示例代码。海湾合作委员会的差异如下:
GCC 4.7.3:g ++ -Wall -Wextra -std = c ++ 0x -O3 -c array-fill.cpp
#include <algorithm>
#include <cstring>
int fref() {
int a[1024];
return a[512] - a[256]; }
int f1() {
int a[1024] = {};
return a[512] - a[256]; }
int f2() {
int a[1024];
std::memset(a, 0, sizeof(a));
return a[512] - a[256]; }
int f3() {
int a[1024];
std::fill(a, a + 100, 0);
return a[512] - a[256]; }
拆卸
objdump -d array-fill.o | C ++ FILT
00000000 <fref()>:
0: b8 00 10 00 00 mov $0x1000,%eax
5: e8 00 00 00 00 call a <fref()+0xa>
a: 29 c4 sub %eax,%esp
c: 8b 84 24 00 08 00 00 mov 0x800(%esp),%eax
13: 2b 84 24 00 04 00 00 sub 0x400(%esp),%eax
1a: 81 c4 00 10 00 00 add $0x1000,%esp
20: c3 ret
21: eb 0d jmp 30 <f1()>
00000030 <f1()>:
30: 31 c0 xor %eax,%eax
32: c3 ret
33: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
39: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi
00000040 <f2()>:
40: b8 00 10 00 00 mov $0x1000,%eax
45: e8 00 00 00 00 call 4a <f2()+0xa>
4a: 29 c4 sub %eax,%esp
4c: 31 c0 xor %eax,%eax
4e: 81 c4 00 10 00 00 add $0x1000,%esp
54: c3 ret
55: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
59: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi
00000060 <f3()>:
60: b8 00 10 00 00 mov $0x1000,%eax
65: e8 00 00 00 00 call 6a <f3()+0xa>
6a: 29 c4 sub %eax,%esp
6c: 89 e0 mov %esp,%eax
6e: 8d 94 24 90 01 00 00 lea 0x190(%esp),%edx
75: c7 00 00 00 00 00 movl $0x0,(%eax)
7b: 83 c0 04 add $0x4,%eax
7e: 39 d0 cmp %edx,%eax
80: 75 f3 jne 75 <f3()+0x15>
82: 8b 84 24 00 08 00 00 mov 0x800(%esp),%eax
89: 2b 84 24 00 04 00 00 sub 0x400(%esp),%eax
90: 81 c4 00 10 00 00 add $0x1000,%esp
96: c3 ret
在这种情况下,C样式初始化(f1
)肯定允许优化!